diff --git a/Crypto/Cipher/AES.py b/Crypto/Cipher/AES.py deleted file mode 100644 index 1237a8c..0000000 --- a/Crypto/Cipher/AES.py +++ /dev/null @@ -1,250 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Cipher/AES.py : AES -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== -""" -Module's constants for the modes of operation supported with AES: - -:var MODE_ECB: :ref:`Electronic Code Book (ECB) ` -:var MODE_CBC: :ref:`Cipher-Block Chaining (CBC) ` -:var MODE_CFB: :ref:`Cipher FeedBack (CFB) ` -:var MODE_OFB: :ref:`Output FeedBack (OFB) ` -:var MODE_CTR: :ref:`CounTer Mode (CTR) ` -:var MODE_OPENPGP: :ref:`OpenPGP Mode ` -:var MODE_CCM: :ref:`Counter with CBC-MAC (CCM) Mode ` -:var MODE_EAX: :ref:`EAX Mode ` -:var MODE_GCM: :ref:`Galois Counter Mode (GCM) ` -:var MODE_SIV: :ref:`Syntethic Initialization Vector (SIV) ` -:var MODE_OCB: :ref:`Offset Code Book (OCB) ` -""" - -import sys - -from Crypto.Cipher import _create_cipher -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - c_size_t, c_uint8_ptr) - -from Crypto.Util import _cpu_features -from Crypto.Random import get_random_bytes - - -_cproto = """ - int AES_start_operation(const uint8_t key[], - size_t key_len, - void **pResult); - int AES_encrypt(const void *state, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int AES_decrypt(const void *state, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int AES_stop_operation(void *state); - """ - - -# Load portable AES -_raw_aes_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_aes", - _cproto) - -# Try to load AES with AES NI instructions -try: - _raw_aesni_lib = None - if _cpu_features.have_aes_ni(): - _raw_aesni_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_aesni", - _cproto.replace("AES", - "AESNI")) -# _raw_aesni may not have been compiled in -except OSError: - pass - - -def _create_base_cipher(dict_parameters): - """This method instantiates and returns a handle to a low-level - base cipher. It will absorb named parameters in the process.""" - - use_aesni = dict_parameters.pop("use_aesni", True) - - try: - key = dict_parameters.pop("key") - except KeyError: - raise TypeError("Missing 'key' parameter") - - if len(key) not in key_size: - raise ValueError("Incorrect AES key length (%d bytes)" % len(key)) - - if use_aesni and _raw_aesni_lib: - start_operation = _raw_aesni_lib.AESNI_start_operation - stop_operation = _raw_aesni_lib.AESNI_stop_operation - else: - start_operation = _raw_aes_lib.AES_start_operation - stop_operation = _raw_aes_lib.AES_stop_operation - - cipher = VoidPointer() - result = start_operation(c_uint8_ptr(key), - c_size_t(len(key)), - cipher.address_of()) - if result: - raise ValueError("Error %X while instantiating the AES cipher" - % result) - return SmartPointer(cipher.get(), stop_operation) - - -def _derive_Poly1305_key_pair(key, nonce): - """Derive a tuple (r, s, nonce) for a Poly1305 MAC. - - If nonce is ``None``, a new 16-byte nonce is generated. - """ - - if len(key) != 32: - raise ValueError("Poly1305 with AES requires a 32-byte key") - - if nonce is None: - nonce = get_random_bytes(16) - elif len(nonce) != 16: - raise ValueError("Poly1305 with AES requires a 16-byte nonce") - - s = new(key[:16], MODE_ECB).encrypt(nonce) - return key[16:], s, nonce - - -def new(key, mode, *args, **kwargs): - """Create a new AES cipher. - - :param key: - The secret key to use in the symmetric cipher. - - It must be 16, 24 or 32 bytes long (respectively for *AES-128*, - *AES-192* or *AES-256*). - - For ``MODE_SIV`` only, it doubles to 32, 48, or 64 bytes. - :type key: bytes/bytearray/memoryview - - :param mode: - The chaining mode to use for encryption or decryption. - If in doubt, use ``MODE_EAX``. - :type mode: One of the supported ``MODE_*`` constants - - :Keyword Arguments: - * **iv** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, - and ``MODE_OPENPGP`` modes). - - The initialization vector to use for encryption or decryption. - - For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 16 bytes long. - - For ``MODE_OPENPGP`` mode only, - it must be 16 bytes long for encryption - and 18 bytes for decryption (in the latter case, it is - actually the *encrypted* IV which was prefixed to the ciphertext). - - If not provided, a random byte string is generated (you must then - read its value with the :attr:`iv` attribute). - - * **nonce** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_CCM``, ``MODE_EAX``, ``MODE_GCM``, - ``MODE_SIV``, ``MODE_OCB``, and ``MODE_CTR``). - - A value that must never be reused for any other encryption done - with this key (except possibly for ``MODE_SIV``, see below). - - For ``MODE_EAX``, ``MODE_GCM`` and ``MODE_SIV`` there are no - restrictions on its length (recommended: **16** bytes). - - For ``MODE_CCM``, its length must be in the range **[7..13]**. - Bear in mind that with CCM there is a trade-off between nonce - length and maximum message size. Recommendation: **11** bytes. - - For ``MODE_OCB``, its length must be in the range **[1..15]** - (recommended: **15**). - - For ``MODE_CTR``, its length must be in the range **[0..15]** - (recommended: **8**). - - For ``MODE_SIV``, the nonce is optional, if it is not specified, - then no nonce is being used, which renders the encryption - deterministic. - - If not provided, for modes other than ``MODE_SIV```, a random - byte string of the recommended length is used (you must then - read its value with the :attr:`nonce` attribute). - - * **segment_size** (*integer*) -- - (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext - are segmented in. It must be a multiple of 8. - If not specified, it will be assumed to be 8. - - * **mac_len** : (*integer*) -- - (Only ``MODE_EAX``, ``MODE_GCM``, ``MODE_OCB``, ``MODE_CCM``) - Length of the authentication tag, in bytes. - - It must be even and in the range **[4..16]**. - The recommended value (and the default, if not specified) is **16**. - - * **msg_len** : (*integer*) -- - (Only ``MODE_CCM``). Length of the message to (de)cipher. - If not specified, ``encrypt`` must be called with the entire message. - Similarly, ``decrypt`` can only be called once. - - * **assoc_len** : (*integer*) -- - (Only ``MODE_CCM``). Length of the associated data. - If not specified, all associated data is buffered internally, - which may represent a problem for very large messages. - - * **initial_value** : (*integer* or *bytes/bytearray/memoryview*) -- - (Only ``MODE_CTR``). - The initial value for the counter. If not present, the cipher will - start counting from 0. The value is incremented by one for each block. - The counter number is encoded in big endian mode. - - * **counter** : (*object*) -- - Instance of ``Crypto.Util.Counter``, which allows full customization - of the counter block. This parameter is incompatible to both ``nonce`` - and ``initial_value``. - - * **use_aesni** : (*boolean*) -- - Use Intel AES-NI hardware extensions (default: use if available). - - :Return: an AES object, of the applicable mode. - """ - - kwargs["add_aes_modes"] = True - return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) - - -MODE_ECB = 1 -MODE_CBC = 2 -MODE_CFB = 3 -MODE_OFB = 5 -MODE_CTR = 6 -MODE_OPENPGP = 7 -MODE_CCM = 8 -MODE_EAX = 9 -MODE_SIV = 10 -MODE_GCM = 11 -MODE_OCB = 12 - -# Size of a data block (in bytes) -block_size = 16 -# Size of a key (in bytes) -key_size = (16, 24, 32) diff --git a/Crypto/Cipher/AES.pyi b/Crypto/Cipher/AES.pyi deleted file mode 100644 index 8f655cf..0000000 --- a/Crypto/Cipher/AES.pyi +++ /dev/null @@ -1,47 +0,0 @@ -from typing import Union, Tuple, Optional, Dict - -from Crypto.Cipher._mode_ecb import EcbMode -from Crypto.Cipher._mode_cbc import CbcMode -from Crypto.Cipher._mode_cfb import CfbMode -from Crypto.Cipher._mode_ofb import OfbMode -from Crypto.Cipher._mode_ctr import CtrMode -from Crypto.Cipher._mode_openpgp import OpenPgpMode -from Crypto.Cipher._mode_ccm import CcmMode -from Crypto.Cipher._mode_eax import EaxMode -from Crypto.Cipher._mode_gcm import GcmMode -from Crypto.Cipher._mode_siv import SivMode -from Crypto.Cipher._mode_ocb import OcbMode - -AESMode = int - -MODE_ECB: AESMode -MODE_CBC: AESMode -MODE_CFB: AESMode -MODE_OFB: AESMode -MODE_CTR: AESMode -MODE_OPENPGP: AESMode -MODE_CCM: AESMode -MODE_EAX: AESMode -MODE_GCM: AESMode -MODE_SIV: AESMode -MODE_OCB: AESMode - -Buffer = Union[bytes, bytearray, memoryview] - -def new(key: Buffer, - mode: AESMode, - iv : Buffer = ..., - IV : Buffer = ..., - nonce : Buffer = ..., - segment_size : int = ..., - mac_len : int = ..., - assoc_len : int = ..., - initial_value : Union[int, Buffer] = ..., - counter : Dict = ..., - use_aesni : bool = ...) -> \ - Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, - OpenPgpMode, CcmMode, EaxMode, GcmMode, - SivMode, OcbMode]: ... - -block_size: int -key_size: Tuple[int, int, int] diff --git a/Crypto/Cipher/ARC2.py b/Crypto/Cipher/ARC2.py deleted file mode 100644 index 0ba7e33..0000000 --- a/Crypto/Cipher/ARC2.py +++ /dev/null @@ -1,175 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Cipher/ARC2.py : ARC2.py -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== -""" -Module's constants for the modes of operation supported with ARC2: - -:var MODE_ECB: :ref:`Electronic Code Book (ECB) ` -:var MODE_CBC: :ref:`Cipher-Block Chaining (CBC) ` -:var MODE_CFB: :ref:`Cipher FeedBack (CFB) ` -:var MODE_OFB: :ref:`Output FeedBack (OFB) ` -:var MODE_CTR: :ref:`CounTer Mode (CTR) ` -:var MODE_OPENPGP: :ref:`OpenPGP Mode ` -:var MODE_EAX: :ref:`EAX Mode ` -""" - -import sys - -from Crypto.Cipher import _create_cipher -from Crypto.Util.py3compat import byte_string -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - c_size_t, c_uint8_ptr) - -_raw_arc2_lib = load_pycryptodome_raw_lib( - "Crypto.Cipher._raw_arc2", - """ - int ARC2_start_operation(const uint8_t key[], - size_t key_len, - size_t effective_key_len, - void **pResult); - int ARC2_encrypt(const void *state, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int ARC2_decrypt(const void *state, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int ARC2_stop_operation(void *state); - """ - ) - - -def _create_base_cipher(dict_parameters): - """This method instantiates and returns a handle to a low-level - base cipher. It will absorb named parameters in the process.""" - - try: - key = dict_parameters.pop("key") - except KeyError: - raise TypeError("Missing 'key' parameter") - - effective_keylen = dict_parameters.pop("effective_keylen", 1024) - - if len(key) not in key_size: - raise ValueError("Incorrect ARC2 key length (%d bytes)" % len(key)) - - if not (40 <= effective_keylen <= 1024): - raise ValueError("'effective_key_len' must be at least 40 and no larger than 1024 " - "(not %d)" % effective_keylen) - - start_operation = _raw_arc2_lib.ARC2_start_operation - stop_operation = _raw_arc2_lib.ARC2_stop_operation - - cipher = VoidPointer() - result = start_operation(c_uint8_ptr(key), - c_size_t(len(key)), - c_size_t(effective_keylen), - cipher.address_of()) - if result: - raise ValueError("Error %X while instantiating the ARC2 cipher" - % result) - - return SmartPointer(cipher.get(), stop_operation) - - -def new(key, mode, *args, **kwargs): - """Create a new RC2 cipher. - - :param key: - The secret key to use in the symmetric cipher. - Its length can vary from 5 to 128 bytes; the actual search space - (and the cipher strength) can be reduced with the ``effective_keylen`` parameter. - :type key: bytes, bytearray, memoryview - - :param mode: - The chaining mode to use for encryption or decryption. - :type mode: One of the supported ``MODE_*`` constants - - :Keyword Arguments: - * **iv** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, - and ``MODE_OPENPGP`` modes). - - The initialization vector to use for encryption or decryption. - - For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. - - For ``MODE_OPENPGP`` mode only, - it must be 8 bytes long for encryption - and 10 bytes for decryption (in the latter case, it is - actually the *encrypted* IV which was prefixed to the ciphertext). - - If not provided, a random byte string is generated (you must then - read its value with the :attr:`iv` attribute). - - * **nonce** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). - - A value that must never be reused for any other encryption done - with this key. - - For ``MODE_EAX`` there are no - restrictions on its length (recommended: **16** bytes). - - For ``MODE_CTR``, its length must be in the range **[0..7]**. - - If not provided for ``MODE_EAX``, a random byte string is generated (you - can read it back via the ``nonce`` attribute). - - * **effective_keylen** (*integer*) -- - Optional. Maximum strength in bits of the actual key used by the ARC2 algorithm. - If the supplied ``key`` parameter is longer (in bits) of the value specified - here, it will be weakened to match it. - If not specified, no limitation is applied. - - * **segment_size** (*integer*) -- - (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext - are segmented in. It must be a multiple of 8. - If not specified, it will be assumed to be 8. - - * **mac_len** : (*integer*) -- - (Only ``MODE_EAX``) - Length of the authentication tag, in bytes. - It must be no longer than 8 (default). - - * **initial_value** : (*integer*) -- - (Only ``MODE_CTR``). The initial value for the counter within - the counter block. By default it is **0**. - - :Return: an ARC2 object, of the applicable mode. - """ - - return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) - -MODE_ECB = 1 -MODE_CBC = 2 -MODE_CFB = 3 -MODE_OFB = 5 -MODE_CTR = 6 -MODE_OPENPGP = 7 -MODE_EAX = 9 - -# Size of a data block (in bytes) -block_size = 8 -# Size of a key (in bytes) -key_size = range(5, 128 + 1) diff --git a/Crypto/Cipher/ARC2.pyi b/Crypto/Cipher/ARC2.pyi deleted file mode 100644 index 055c424..0000000 --- a/Crypto/Cipher/ARC2.pyi +++ /dev/null @@ -1,35 +0,0 @@ -from typing import Union, Dict, Iterable - -from Crypto.Cipher._mode_ecb import EcbMode -from Crypto.Cipher._mode_cbc import CbcMode -from Crypto.Cipher._mode_cfb import CfbMode -from Crypto.Cipher._mode_ofb import OfbMode -from Crypto.Cipher._mode_ctr import CtrMode -from Crypto.Cipher._mode_openpgp import OpenPgpMode -from Crypto.Cipher._mode_eax import EaxMode - -ARC2Mode = int - -MODE_ECB: ARC2Mode -MODE_CBC: ARC2Mode -MODE_CFB: ARC2Mode -MODE_OFB: ARC2Mode -MODE_CTR: ARC2Mode -MODE_OPENPGP: ARC2Mode -MODE_EAX: ARC2Mode - -Buffer = Union[bytes, bytearray, memoryview] - -def new(key: Buffer, - mode: ARC2Mode, - iv : Buffer = ..., - IV : Buffer = ..., - nonce : Buffer = ..., - segment_size : int = ..., - mac_len : int = ..., - initial_value : Union[int, Buffer] = ..., - counter : Dict = ...) -> \ - Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... - -block_size: int -key_size: Iterable[int] diff --git a/Crypto/Cipher/ARC4.py b/Crypto/Cipher/ARC4.py deleted file mode 100644 index 7150ea6..0000000 --- a/Crypto/Cipher/ARC4.py +++ /dev/null @@ -1,137 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Cipher/ARC4.py : ARC4 -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -from Crypto.Util.py3compat import b - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - create_string_buffer, get_raw_buffer, - SmartPointer, c_size_t, c_uint8_ptr) - - -_raw_arc4_lib = load_pycryptodome_raw_lib("Crypto.Cipher._ARC4", """ - int ARC4_stream_encrypt(void *rc4State, const uint8_t in[], - uint8_t out[], size_t len); - int ARC4_stream_init(uint8_t *key, size_t keylen, - void **pRc4State); - int ARC4_stream_destroy(void *rc4State); - """) - - -class ARC4Cipher: - """ARC4 cipher object. Do not create it directly. Use - :func:`Crypto.Cipher.ARC4.new` instead. - """ - - def __init__(self, key, *args, **kwargs): - """Initialize an ARC4 cipher object - - See also `new()` at the module level.""" - - if len(args) > 0: - ndrop = args[0] - args = args[1:] - else: - ndrop = kwargs.pop('drop', 0) - - if len(key) not in key_size: - raise ValueError("Incorrect ARC4 key length (%d bytes)" % - len(key)) - - self._state = VoidPointer() - result = _raw_arc4_lib.ARC4_stream_init(c_uint8_ptr(key), - c_size_t(len(key)), - self._state.address_of()) - if result != 0: - raise ValueError("Error %d while creating the ARC4 cipher" - % result) - self._state = SmartPointer(self._state.get(), - _raw_arc4_lib.ARC4_stream_destroy) - - if ndrop > 0: - # This is OK even if the cipher is used for decryption, - # since encrypt and decrypt are actually the same thing - # with ARC4. - self.encrypt(b'\x00' * ndrop) - - self.block_size = 1 - self.key_size = len(key) - - def encrypt(self, plaintext): - """Encrypt a piece of data. - - :param plaintext: The data to encrypt, of any size. - :type plaintext: bytes, bytearray, memoryview - :returns: the encrypted byte string, of equal length as the - plaintext. - """ - - ciphertext = create_string_buffer(len(plaintext)) - result = _raw_arc4_lib.ARC4_stream_encrypt(self._state.get(), - c_uint8_ptr(plaintext), - ciphertext, - c_size_t(len(plaintext))) - if result: - raise ValueError("Error %d while encrypting with RC4" % result) - return get_raw_buffer(ciphertext) - - def decrypt(self, ciphertext): - """Decrypt a piece of data. - - :param ciphertext: The data to decrypt, of any size. - :type ciphertext: bytes, bytearray, memoryview - :returns: the decrypted byte string, of equal length as the - ciphertext. - """ - - try: - return self.encrypt(ciphertext) - except ValueError as e: - raise ValueError(str(e).replace("enc", "dec")) - - -def new(key, *args, **kwargs): - """Create a new ARC4 cipher. - - :param key: - The secret key to use in the symmetric cipher. - Its length must be in the range ``[5..256]``. - The recommended length is 16 bytes. - :type key: bytes, bytearray, memoryview - - :Keyword Arguments: - * *drop* (``integer``) -- - The amount of bytes to discard from the initial part of the keystream. - In fact, such part has been found to be distinguishable from random - data (while it shouldn't) and also correlated to key. - - The recommended value is 3072_ bytes. The default value is 0. - - :Return: an `ARC4Cipher` object - - .. _3072: http://eprint.iacr.org/2002/067.pdf - """ - return ARC4Cipher(key, *args, **kwargs) - -# Size of a data block (in bytes) -block_size = 1 -# Size of a key (in bytes) -key_size = range(5, 256+1) diff --git a/Crypto/Cipher/ARC4.pyi b/Crypto/Cipher/ARC4.pyi deleted file mode 100644 index 2e75d6f..0000000 --- a/Crypto/Cipher/ARC4.pyi +++ /dev/null @@ -1,16 +0,0 @@ -from typing import Any, Union, Iterable - -Buffer = Union[bytes, bytearray, memoryview] - -class ARC4Cipher: - block_size: int - key_size: int - - def __init__(self, key: Buffer, *args: Any, **kwargs: Any) -> None: ... - def encrypt(self, plaintext: Buffer) -> bytes: ... - def decrypt(self, ciphertext: Buffer) -> bytes: ... - -def new(key: Buffer, drop : int = ...) -> ARC4Cipher: ... - -block_size: int -key_size: Iterable[int] diff --git a/Crypto/Cipher/Blowfish.py b/Crypto/Cipher/Blowfish.py deleted file mode 100644 index 6005ffe..0000000 --- a/Crypto/Cipher/Blowfish.py +++ /dev/null @@ -1,159 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Cipher/Blowfish.py : Blowfish -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== -""" -Module's constants for the modes of operation supported with Blowfish: - -:var MODE_ECB: :ref:`Electronic Code Book (ECB) ` -:var MODE_CBC: :ref:`Cipher-Block Chaining (CBC) ` -:var MODE_CFB: :ref:`Cipher FeedBack (CFB) ` -:var MODE_OFB: :ref:`Output FeedBack (OFB) ` -:var MODE_CTR: :ref:`CounTer Mode (CTR) ` -:var MODE_OPENPGP: :ref:`OpenPGP Mode ` -:var MODE_EAX: :ref:`EAX Mode ` -""" - -import sys - -from Crypto.Cipher import _create_cipher -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, c_size_t, - c_uint8_ptr) - -_raw_blowfish_lib = load_pycryptodome_raw_lib( - "Crypto.Cipher._raw_blowfish", - """ - int Blowfish_start_operation(const uint8_t key[], - size_t key_len, - void **pResult); - int Blowfish_encrypt(const void *state, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int Blowfish_decrypt(const void *state, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int Blowfish_stop_operation(void *state); - """ - ) - - -def _create_base_cipher(dict_parameters): - """This method instantiates and returns a smart pointer to - a low-level base cipher. It will absorb named parameters in - the process.""" - - try: - key = dict_parameters.pop("key") - except KeyError: - raise TypeError("Missing 'key' parameter") - - if len(key) not in key_size: - raise ValueError("Incorrect Blowfish key length (%d bytes)" % len(key)) - - start_operation = _raw_blowfish_lib.Blowfish_start_operation - stop_operation = _raw_blowfish_lib.Blowfish_stop_operation - - void_p = VoidPointer() - result = start_operation(c_uint8_ptr(key), - c_size_t(len(key)), - void_p.address_of()) - if result: - raise ValueError("Error %X while instantiating the Blowfish cipher" - % result) - return SmartPointer(void_p.get(), stop_operation) - - -def new(key, mode, *args, **kwargs): - """Create a new Blowfish cipher - - :param key: - The secret key to use in the symmetric cipher. - Its length can vary from 5 to 56 bytes. - :type key: bytes, bytearray, memoryview - - :param mode: - The chaining mode to use for encryption or decryption. - :type mode: One of the supported ``MODE_*`` constants - - :Keyword Arguments: - * **iv** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, - and ``MODE_OPENPGP`` modes). - - The initialization vector to use for encryption or decryption. - - For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. - - For ``MODE_OPENPGP`` mode only, - it must be 8 bytes long for encryption - and 10 bytes for decryption (in the latter case, it is - actually the *encrypted* IV which was prefixed to the ciphertext). - - If not provided, a random byte string is generated (you must then - read its value with the :attr:`iv` attribute). - - * **nonce** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). - - A value that must never be reused for any other encryption done - with this key. - - For ``MODE_EAX`` there are no - restrictions on its length (recommended: **16** bytes). - - For ``MODE_CTR``, its length must be in the range **[0..7]**. - - If not provided for ``MODE_EAX``, a random byte string is generated (you - can read it back via the ``nonce`` attribute). - - * **segment_size** (*integer*) -- - (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext - are segmented in. It must be a multiple of 8. - If not specified, it will be assumed to be 8. - - * **mac_len** : (*integer*) -- - (Only ``MODE_EAX``) - Length of the authentication tag, in bytes. - It must be no longer than 8 (default). - - * **initial_value** : (*integer*) -- - (Only ``MODE_CTR``). The initial value for the counter within - the counter block. By default it is **0**. - - :Return: a Blowfish object, of the applicable mode. - """ - - return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) - -MODE_ECB = 1 -MODE_CBC = 2 -MODE_CFB = 3 -MODE_OFB = 5 -MODE_CTR = 6 -MODE_OPENPGP = 7 -MODE_EAX = 9 - -# Size of a data block (in bytes) -block_size = 8 -# Size of a key (in bytes) -key_size = range(4, 56 + 1) diff --git a/Crypto/Cipher/Blowfish.pyi b/Crypto/Cipher/Blowfish.pyi deleted file mode 100644 index eff9da9..0000000 --- a/Crypto/Cipher/Blowfish.pyi +++ /dev/null @@ -1,35 +0,0 @@ -from typing import Union, Dict, Iterable - -from Crypto.Cipher._mode_ecb import EcbMode -from Crypto.Cipher._mode_cbc import CbcMode -from Crypto.Cipher._mode_cfb import CfbMode -from Crypto.Cipher._mode_ofb import OfbMode -from Crypto.Cipher._mode_ctr import CtrMode -from Crypto.Cipher._mode_openpgp import OpenPgpMode -from Crypto.Cipher._mode_eax import EaxMode - -BlowfishMode = int - -MODE_ECB: BlowfishMode -MODE_CBC: BlowfishMode -MODE_CFB: BlowfishMode -MODE_OFB: BlowfishMode -MODE_CTR: BlowfishMode -MODE_OPENPGP: BlowfishMode -MODE_EAX: BlowfishMode - -Buffer = Union[bytes, bytearray, memoryview] - -def new(key: Buffer, - mode: BlowfishMode, - iv : Buffer = ..., - IV : Buffer = ..., - nonce : Buffer = ..., - segment_size : int = ..., - mac_len : int = ..., - initial_value : Union[int, Buffer] = ..., - counter : Dict = ...) -> \ - Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... - -block_size: int -key_size: Iterable[int] diff --git a/Crypto/Cipher/CAST.py b/Crypto/Cipher/CAST.py deleted file mode 100644 index c7e82c1..0000000 --- a/Crypto/Cipher/CAST.py +++ /dev/null @@ -1,159 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Cipher/CAST.py : CAST -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== -""" -Module's constants for the modes of operation supported with CAST: - -:var MODE_ECB: :ref:`Electronic Code Book (ECB) ` -:var MODE_CBC: :ref:`Cipher-Block Chaining (CBC) ` -:var MODE_CFB: :ref:`Cipher FeedBack (CFB) ` -:var MODE_OFB: :ref:`Output FeedBack (OFB) ` -:var MODE_CTR: :ref:`CounTer Mode (CTR) ` -:var MODE_OPENPGP: :ref:`OpenPGP Mode ` -:var MODE_EAX: :ref:`EAX Mode ` -""" - -import sys - -from Crypto.Cipher import _create_cipher -from Crypto.Util.py3compat import byte_string -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - c_size_t, c_uint8_ptr) - -_raw_cast_lib = load_pycryptodome_raw_lib( - "Crypto.Cipher._raw_cast", - """ - int CAST_start_operation(const uint8_t key[], - size_t key_len, - void **pResult); - int CAST_encrypt(const void *state, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int CAST_decrypt(const void *state, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int CAST_stop_operation(void *state); - """) - - -def _create_base_cipher(dict_parameters): - """This method instantiates and returns a handle to a low-level - base cipher. It will absorb named parameters in the process.""" - - try: - key = dict_parameters.pop("key") - except KeyError: - raise TypeError("Missing 'key' parameter") - - if len(key) not in key_size: - raise ValueError("Incorrect CAST key length (%d bytes)" % len(key)) - - start_operation = _raw_cast_lib.CAST_start_operation - stop_operation = _raw_cast_lib.CAST_stop_operation - - cipher = VoidPointer() - result = start_operation(c_uint8_ptr(key), - c_size_t(len(key)), - cipher.address_of()) - if result: - raise ValueError("Error %X while instantiating the CAST cipher" - % result) - - return SmartPointer(cipher.get(), stop_operation) - - -def new(key, mode, *args, **kwargs): - """Create a new CAST cipher - - :param key: - The secret key to use in the symmetric cipher. - Its length can vary from 5 to 16 bytes. - :type key: bytes, bytearray, memoryview - - :param mode: - The chaining mode to use for encryption or decryption. - :type mode: One of the supported ``MODE_*`` constants - - :Keyword Arguments: - * **iv** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, - and ``MODE_OPENPGP`` modes). - - The initialization vector to use for encryption or decryption. - - For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. - - For ``MODE_OPENPGP`` mode only, - it must be 8 bytes long for encryption - and 10 bytes for decryption (in the latter case, it is - actually the *encrypted* IV which was prefixed to the ciphertext). - - If not provided, a random byte string is generated (you must then - read its value with the :attr:`iv` attribute). - - * **nonce** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). - - A value that must never be reused for any other encryption done - with this key. - - For ``MODE_EAX`` there are no - restrictions on its length (recommended: **16** bytes). - - For ``MODE_CTR``, its length must be in the range **[0..7]**. - - If not provided for ``MODE_EAX``, a random byte string is generated (you - can read it back via the ``nonce`` attribute). - - * **segment_size** (*integer*) -- - (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext - are segmented in. It must be a multiple of 8. - If not specified, it will be assumed to be 8. - - * **mac_len** : (*integer*) -- - (Only ``MODE_EAX``) - Length of the authentication tag, in bytes. - It must be no longer than 8 (default). - - * **initial_value** : (*integer*) -- - (Only ``MODE_CTR``). The initial value for the counter within - the counter block. By default it is **0**. - - :Return: a CAST object, of the applicable mode. - """ - - return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) - -MODE_ECB = 1 -MODE_CBC = 2 -MODE_CFB = 3 -MODE_OFB = 5 -MODE_CTR = 6 -MODE_OPENPGP = 7 -MODE_EAX = 9 - -# Size of a data block (in bytes) -block_size = 8 -# Size of a key (in bytes) -key_size = range(5, 16 + 1) diff --git a/Crypto/Cipher/CAST.pyi b/Crypto/Cipher/CAST.pyi deleted file mode 100644 index a0cb6af..0000000 --- a/Crypto/Cipher/CAST.pyi +++ /dev/null @@ -1,35 +0,0 @@ -from typing import Union, Dict, Iterable - -from Crypto.Cipher._mode_ecb import EcbMode -from Crypto.Cipher._mode_cbc import CbcMode -from Crypto.Cipher._mode_cfb import CfbMode -from Crypto.Cipher._mode_ofb import OfbMode -from Crypto.Cipher._mode_ctr import CtrMode -from Crypto.Cipher._mode_openpgp import OpenPgpMode -from Crypto.Cipher._mode_eax import EaxMode - -CASTMode = int - -MODE_ECB: CASTMode -MODE_CBC: CASTMode -MODE_CFB: CASTMode -MODE_OFB: CASTMode -MODE_CTR: CASTMode -MODE_OPENPGP: CASTMode -MODE_EAX: CASTMode - -Buffer = Union[bytes, bytearray, memoryview] - -def new(key: Buffer, - mode: CASTMode, - iv : Buffer = ..., - IV : Buffer = ..., - nonce : Buffer = ..., - segment_size : int = ..., - mac_len : int = ..., - initial_value : Union[int, Buffer] = ..., - counter : Dict = ...) -> \ - Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... - -block_size: int -key_size : Iterable[int] diff --git a/Crypto/Cipher/ChaCha20.py b/Crypto/Cipher/ChaCha20.py deleted file mode 100644 index 9bd2252..0000000 --- a/Crypto/Cipher/ChaCha20.py +++ /dev/null @@ -1,287 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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 Crypto.Random import get_random_bytes - -from Crypto.Util.py3compat import _copy_bytes -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - create_string_buffer, - get_raw_buffer, VoidPointer, - SmartPointer, c_size_t, - c_uint8_ptr, c_ulong, - is_writeable_buffer) - -_raw_chacha20_lib = load_pycryptodome_raw_lib("Crypto.Cipher._chacha20", - """ - int chacha20_init(void **pState, - const uint8_t *key, - size_t keySize, - const uint8_t *nonce, - size_t nonceSize); - - int chacha20_destroy(void *state); - - int chacha20_encrypt(void *state, - const uint8_t in[], - uint8_t out[], - size_t len); - - int chacha20_seek(void *state, - unsigned long block_high, - unsigned long block_low, - unsigned offset); - int hchacha20( const uint8_t key[32], - const uint8_t nonce16[16], - uint8_t subkey[32]); - """) - - -def _HChaCha20(key, nonce): - - assert(len(key) == 32) - assert(len(nonce) == 16) - - subkey = bytearray(32) - result = _raw_chacha20_lib.hchacha20( - c_uint8_ptr(key), - c_uint8_ptr(nonce), - c_uint8_ptr(subkey)) - if result: - raise ValueError("Error %d when deriving subkey with HChaCha20" % result) - - return subkey - - -class ChaCha20Cipher(object): - """ChaCha20 (or XChaCha20) cipher object. - Do not create it directly. Use :py:func:`new` instead. - - :var nonce: The nonce with length 8, 12 or 24 bytes - :vartype nonce: bytes - """ - - block_size = 1 - - def __init__(self, key, nonce): - """Initialize a ChaCha20/XChaCha20 cipher object - - See also `new()` at the module level.""" - - self.nonce = _copy_bytes(None, None, nonce) - - # XChaCha20 requires a key derivation with HChaCha20 - # See 2.3 in https://tools.ietf.org/html/draft-arciszewski-xchacha-03 - if len(nonce) == 24: - key = _HChaCha20(key, nonce[:16]) - nonce = b'\x00' * 4 + nonce[16:] - self._name = "XChaCha20" - else: - self._name = "ChaCha20" - nonce = self.nonce - - self._next = ( self.encrypt, self.decrypt ) - - self._state = VoidPointer() - result = _raw_chacha20_lib.chacha20_init( - self._state.address_of(), - c_uint8_ptr(key), - c_size_t(len(key)), - nonce, - c_size_t(len(nonce))) - if result: - raise ValueError("Error %d instantiating a %s cipher" % (result, - self._name)) - self._state = SmartPointer(self._state.get(), - _raw_chacha20_lib.chacha20_destroy) - - def encrypt(self, plaintext, output=None): - """Encrypt a piece of data. - - Args: - plaintext(bytes/bytearray/memoryview): The data to encrypt, of any size. - Keyword Args: - output(bytes/bytearray/memoryview): The location where the ciphertext - is written to. If ``None``, the ciphertext is returned. - Returns: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if self.encrypt not in self._next: - raise TypeError("Cipher object can only be used for decryption") - self._next = ( self.encrypt, ) - return self._encrypt(plaintext, output) - - def _encrypt(self, plaintext, output): - """Encrypt without FSM checks""" - - if output is None: - ciphertext = create_string_buffer(len(plaintext)) - else: - ciphertext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(plaintext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = _raw_chacha20_lib.chacha20_encrypt( - self._state.get(), - c_uint8_ptr(plaintext), - c_uint8_ptr(ciphertext), - c_size_t(len(plaintext))) - if result: - raise ValueError("Error %d while encrypting with %s" % (result, self._name)) - - if output is None: - return get_raw_buffer(ciphertext) - else: - return None - - def decrypt(self, ciphertext, output=None): - """Decrypt a piece of data. - - Args: - ciphertext(bytes/bytearray/memoryview): The data to decrypt, of any size. - Keyword Args: - output(bytes/bytearray/memoryview): The location where the plaintext - is written to. If ``None``, the plaintext is returned. - Returns: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if self.decrypt not in self._next: - raise TypeError("Cipher object can only be used for encryption") - self._next = ( self.decrypt, ) - - try: - return self._encrypt(ciphertext, output) - except ValueError as e: - raise ValueError(str(e).replace("enc", "dec")) - - def seek(self, position): - """Seek to a certain position in the key stream. - - Args: - position (integer): - The absolute position within the key stream, in bytes. - """ - - position, offset = divmod(position, 64) - block_low = position & 0xFFFFFFFF - block_high = position >> 32 - - result = _raw_chacha20_lib.chacha20_seek( - self._state.get(), - c_ulong(block_high), - c_ulong(block_low), - offset - ) - if result: - raise ValueError("Error %d while seeking with %s" % (result, self._name)) - - -def _derive_Poly1305_key_pair(key, nonce): - """Derive a tuple (r, s, nonce) for a Poly1305 MAC. - - If nonce is ``None``, a new 12-byte nonce is generated. - """ - - if len(key) != 32: - raise ValueError("Poly1305 with ChaCha20 requires a 32-byte key") - - if nonce is None: - padded_nonce = nonce = get_random_bytes(12) - elif len(nonce) == 8: - # See RFC7538, 2.6: [...] ChaCha20 as specified here requires a 96-bit - # nonce. So if the provided nonce is only 64-bit, then the first 32 - # bits of the nonce will be set to a constant number. - # This will usually be zero, but for protocols with multiple senders it may be - # different for each sender, but should be the same for all - # invocations of the function with the same key by a particular - # sender. - padded_nonce = b'\x00\x00\x00\x00' + nonce - elif len(nonce) == 12: - padded_nonce = nonce - else: - raise ValueError("Poly1305 with ChaCha20 requires an 8- or 12-byte nonce") - - rs = new(key=key, nonce=padded_nonce).encrypt(b'\x00' * 32) - return rs[:16], rs[16:], nonce - - -def new(**kwargs): - """Create a new ChaCha20 or XChaCha20 cipher - - Keyword Args: - key (bytes/bytearray/memoryview): The secret key to use. - It must be 32 bytes long. - nonce (bytes/bytearray/memoryview): A mandatory value that - must never be reused for any other encryption - done with this key. - - For ChaCha20, it must be 8 or 12 bytes long. - - For XChaCha20, it must be 24 bytes long. - - If not provided, 8 bytes will be randomly generated - (you can find them back in the ``nonce`` attribute). - - :Return: a :class:`Crypto.Cipher.ChaCha20.ChaCha20Cipher` object - """ - - try: - key = kwargs.pop("key") - except KeyError as e: - raise TypeError("Missing parameter %s" % e) - - nonce = kwargs.pop("nonce", None) - if nonce is None: - nonce = get_random_bytes(8) - - if len(key) != 32: - raise ValueError("ChaCha20/XChaCha20 key must be 32 bytes long") - - if len(nonce) not in (8, 12, 24): - raise ValueError("Nonce must be 8/12 bytes(ChaCha20) or 24 bytes (XChaCha20)") - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return ChaCha20Cipher(key, nonce) - -# Size of a data block (in bytes) -block_size = 1 - -# Size of a key (in bytes) -key_size = 32 diff --git a/Crypto/Cipher/ChaCha20.pyi b/Crypto/Cipher/ChaCha20.pyi deleted file mode 100644 index 3d00a1d..0000000 --- a/Crypto/Cipher/ChaCha20.pyi +++ /dev/null @@ -1,25 +0,0 @@ -from typing import Union, overload - -Buffer = Union[bytes, bytearray, memoryview] - -def _HChaCha20(key: Buffer, nonce: Buffer) -> bytearray: ... - -class ChaCha20Cipher: - block_size: int - nonce: bytes - - def __init__(self, key: Buffer, nonce: Buffer) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - def seek(self, position: int) -> None: ... - -def new(key: Buffer, nonce: Buffer = ...) -> ChaCha20Cipher: ... - -block_size: int -key_size: int diff --git a/Crypto/Cipher/ChaCha20_Poly1305.py b/Crypto/Cipher/ChaCha20_Poly1305.py deleted file mode 100644 index 21ddca3..0000000 --- a/Crypto/Cipher/ChaCha20_Poly1305.py +++ /dev/null @@ -1,336 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2018, Helder Eijs -# 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 binascii import unhexlify - -from Crypto.Cipher import ChaCha20 -from Crypto.Cipher.ChaCha20 import _HChaCha20 -from Crypto.Hash import Poly1305, BLAKE2s - -from Crypto.Random import get_random_bytes - -from Crypto.Util.number import long_to_bytes -from Crypto.Util.py3compat import _copy_bytes, bord -from Crypto.Util._raw_api import is_buffer - - -def _enum(**enums): - return type('Enum', (), enums) - - -_CipherStatus = _enum(PROCESSING_AUTH_DATA=1, - PROCESSING_CIPHERTEXT=2, - PROCESSING_DONE=3) - - -class ChaCha20Poly1305Cipher(object): - """ChaCha20-Poly1305 and XChaCha20-Poly1305 cipher object. - Do not create it directly. Use :py:func:`new` instead. - - :var nonce: The nonce with length 8, 12 or 24 bytes - :vartype nonce: byte string - """ - - def __init__(self, key, nonce): - """Initialize a ChaCha20-Poly1305 AEAD cipher object - - See also `new()` at the module level.""" - - self.nonce = _copy_bytes(None, None, nonce) - - self._next = (self.update, self.encrypt, self.decrypt, self.digest, - self.verify) - - self._authenticator = Poly1305.new(key=key, nonce=nonce, cipher=ChaCha20) - - self._cipher = ChaCha20.new(key=key, nonce=nonce) - self._cipher.seek(64) # Block counter starts at 1 - - self._len_aad = 0 - self._len_ct = 0 - self._mac_tag = None - self._status = _CipherStatus.PROCESSING_AUTH_DATA - - def update(self, data): - """Protect the associated data. - - Associated data (also known as *additional authenticated data* - AAD) - is the piece of the message that must stay in the clear, while - still allowing the receiver to verify its integrity. - An example is packet headers. - - The associated data (possibly split into multiple segments) is - fed into :meth:`update` before any call to :meth:`decrypt` or :meth:`encrypt`. - If there is no associated data, :meth:`update` is not called. - - :param bytes/bytearray/memoryview assoc_data: - A piece of associated data. There are no restrictions on its size. - """ - - if self.update not in self._next: - raise TypeError("update() method cannot be called") - - self._len_aad += len(data) - self._authenticator.update(data) - - def _pad_aad(self): - - assert(self._status == _CipherStatus.PROCESSING_AUTH_DATA) - if self._len_aad & 0x0F: - self._authenticator.update(b'\x00' * (16 - (self._len_aad & 0x0F))) - self._status = _CipherStatus.PROCESSING_CIPHERTEXT - - def encrypt(self, plaintext, output=None): - """Encrypt a piece of data. - - Args: - plaintext(bytes/bytearray/memoryview): The data to encrypt, of any size. - Keyword Args: - output(bytes/bytearray/memoryview): The location where the ciphertext - is written to. If ``None``, the ciphertext is returned. - Returns: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if self.encrypt not in self._next: - raise TypeError("encrypt() method cannot be called") - - if self._status == _CipherStatus.PROCESSING_AUTH_DATA: - self._pad_aad() - - self._next = (self.encrypt, self.digest) - - result = self._cipher.encrypt(plaintext, output=output) - self._len_ct += len(plaintext) - if output is None: - self._authenticator.update(result) - else: - self._authenticator.update(output) - return result - - def decrypt(self, ciphertext, output=None): - """Decrypt a piece of data. - - Args: - ciphertext(bytes/bytearray/memoryview): The data to decrypt, of any size. - Keyword Args: - output(bytes/bytearray/memoryview): The location where the plaintext - is written to. If ``None``, the plaintext is returned. - Returns: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if self.decrypt not in self._next: - raise TypeError("decrypt() method cannot be called") - - if self._status == _CipherStatus.PROCESSING_AUTH_DATA: - self._pad_aad() - - self._next = (self.decrypt, self.verify) - - self._len_ct += len(ciphertext) - self._authenticator.update(ciphertext) - return self._cipher.decrypt(ciphertext, output=output) - - def _compute_mac(self): - """Finalize the cipher (if not done already) and return the MAC.""" - - if self._mac_tag: - assert(self._status == _CipherStatus.PROCESSING_DONE) - return self._mac_tag - - assert(self._status != _CipherStatus.PROCESSING_DONE) - - if self._status == _CipherStatus.PROCESSING_AUTH_DATA: - self._pad_aad() - - if self._len_ct & 0x0F: - self._authenticator.update(b'\x00' * (16 - (self._len_ct & 0x0F))) - - self._status = _CipherStatus.PROCESSING_DONE - - self._authenticator.update(long_to_bytes(self._len_aad, 8)[::-1]) - self._authenticator.update(long_to_bytes(self._len_ct, 8)[::-1]) - self._mac_tag = self._authenticator.digest() - return self._mac_tag - - def digest(self): - """Compute the *binary* authentication tag (MAC). - - :Return: the MAC tag, as 16 ``bytes``. - """ - - if self.digest not in self._next: - raise TypeError("digest() method cannot be called") - self._next = (self.digest,) - - return self._compute_mac() - - def hexdigest(self): - """Compute the *printable* authentication tag (MAC). - - This method is like :meth:`digest`. - - :Return: the MAC tag, as a hexadecimal string. - """ - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def verify(self, received_mac_tag): - """Validate the *binary* authentication tag (MAC). - - The receiver invokes this method at the very end, to - check if the associated data (if any) and the decrypted - messages are valid. - - :param bytes/bytearray/memoryview received_mac_tag: - This is the 16-byte *binary* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - if self.verify not in self._next: - raise TypeError("verify() cannot be called" - " when encrypting a message") - self._next = (self.verify,) - - secret = get_random_bytes(16) - - self._compute_mac() - - mac1 = BLAKE2s.new(digest_bits=160, key=secret, - data=self._mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, - data=received_mac_tag) - - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") - - def hexverify(self, hex_mac_tag): - """Validate the *printable* authentication tag (MAC). - - This method is like :meth:`verify`. - - :param string hex_mac_tag: - This is the *printable* MAC. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - self.verify(unhexlify(hex_mac_tag)) - - def encrypt_and_digest(self, plaintext): - """Perform :meth:`encrypt` and :meth:`digest` in one step. - - :param plaintext: The data to encrypt, of any size. - :type plaintext: bytes/bytearray/memoryview - :return: a tuple with two ``bytes`` objects: - - - the ciphertext, of equal length as the plaintext - - the 16-byte MAC tag - """ - - return self.encrypt(plaintext), self.digest() - - def decrypt_and_verify(self, ciphertext, received_mac_tag): - """Perform :meth:`decrypt` and :meth:`verify` in one step. - - :param ciphertext: The piece of data to decrypt. - :type ciphertext: bytes/bytearray/memoryview - :param bytes received_mac_tag: - This is the 16-byte *binary* MAC, as received from the sender. - :return: the decrypted data (as ``bytes``) - :raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - plaintext = self.decrypt(ciphertext) - self.verify(received_mac_tag) - return plaintext - - -def new(**kwargs): - """Create a new ChaCha20-Poly1305 or XChaCha20-Poly1305 AEAD cipher. - - :keyword key: The secret key to use. It must be 32 bytes long. - :type key: byte string - - :keyword nonce: - A value that must never be reused for any other encryption - done with this key. - - For ChaCha20-Poly1305, it must be 8 or 12 bytes long. - - For XChaCha20-Poly1305, it must be 24 bytes long. - - If not provided, 12 ``bytes`` will be generated randomly - (you can find them back in the ``nonce`` attribute). - :type nonce: bytes, bytearray, memoryview - - :Return: a :class:`Crypto.Cipher.ChaCha20.ChaCha20Poly1305Cipher` object - """ - - try: - key = kwargs.pop("key") - except KeyError as e: - raise TypeError("Missing parameter %s" % e) - - self._len_ct += len(plaintext) - - if len(key) != 32: - raise ValueError("Key must be 32 bytes long") - - nonce = kwargs.pop("nonce", None) - if nonce is None: - nonce = get_random_bytes(12) - - if len(nonce) in (8, 12): - pass - elif len(nonce) == 24: - key = _HChaCha20(key, nonce[:16]) - nonce = b'\x00\x00\x00\x00' + nonce[16:] - else: - raise ValueError("Nonce must be 8, 12 or 24 bytes long") - - if not is_buffer(nonce): - raise TypeError("nonce must be bytes, bytearray or memoryview") - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return ChaCha20Poly1305Cipher(key, nonce) - - -# Size of a key (in bytes) -key_size = 32 diff --git a/Crypto/Cipher/ChaCha20_Poly1305.pyi b/Crypto/Cipher/ChaCha20_Poly1305.pyi deleted file mode 100644 index ef0450f..0000000 --- a/Crypto/Cipher/ChaCha20_Poly1305.pyi +++ /dev/null @@ -1,28 +0,0 @@ -from typing import Union, Tuple, overload - -Buffer = Union[bytes, bytearray, memoryview] - -class ChaCha20Poly1305Cipher: - nonce: bytes - - def __init__(self, key: Buffer, nonce: Buffer) -> None: ... - def update(self, data: Buffer) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, received_mac_tag: Buffer) -> None: ... - def hexverify(self, received_mac_tag: str) -> None: ... - def encrypt_and_digest(self, plaintext: Buffer) -> Tuple[bytes, bytes]: ... - def decrypt_and_verify(self, ciphertext: Buffer, received_mac_tag: Buffer) -> bytes: ... - -def new(key: Buffer, nonce: Buffer = ...) -> ChaCha20Poly1305Cipher: ... - -block_size: int -key_size: int diff --git a/Crypto/Cipher/DES.py b/Crypto/Cipher/DES.py deleted file mode 100644 index 5cc286a..0000000 --- a/Crypto/Cipher/DES.py +++ /dev/null @@ -1,158 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Cipher/DES.py : DES -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== -""" -Module's constants for the modes of operation supported with Single DES: - -:var MODE_ECB: :ref:`Electronic Code Book (ECB) ` -:var MODE_CBC: :ref:`Cipher-Block Chaining (CBC) ` -:var MODE_CFB: :ref:`Cipher FeedBack (CFB) ` -:var MODE_OFB: :ref:`Output FeedBack (OFB) ` -:var MODE_CTR: :ref:`CounTer Mode (CTR) ` -:var MODE_OPENPGP: :ref:`OpenPGP Mode ` -:var MODE_EAX: :ref:`EAX Mode ` -""" - -import sys - -from Crypto.Cipher import _create_cipher -from Crypto.Util.py3compat import byte_string -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - c_size_t, c_uint8_ptr) - -_raw_des_lib = load_pycryptodome_raw_lib( - "Crypto.Cipher._raw_des", - """ - int DES_start_operation(const uint8_t key[], - size_t key_len, - void **pResult); - int DES_encrypt(const void *state, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int DES_decrypt(const void *state, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int DES_stop_operation(void *state); - """) - - -def _create_base_cipher(dict_parameters): - """This method instantiates and returns a handle to a low-level - base cipher. It will absorb named parameters in the process.""" - - try: - key = dict_parameters.pop("key") - except KeyError: - raise TypeError("Missing 'key' parameter") - - if len(key) != key_size: - raise ValueError("Incorrect DES key length (%d bytes)" % len(key)) - - start_operation = _raw_des_lib.DES_start_operation - stop_operation = _raw_des_lib.DES_stop_operation - - cipher = VoidPointer() - result = start_operation(c_uint8_ptr(key), - c_size_t(len(key)), - cipher.address_of()) - if result: - raise ValueError("Error %X while instantiating the DES cipher" - % result) - return SmartPointer(cipher.get(), stop_operation) - - -def new(key, mode, *args, **kwargs): - """Create a new DES cipher. - - :param key: - The secret key to use in the symmetric cipher. - It must be 8 byte long. The parity bits will be ignored. - :type key: bytes/bytearray/memoryview - - :param mode: - The chaining mode to use for encryption or decryption. - :type mode: One of the supported ``MODE_*`` constants - - :Keyword Arguments: - * **iv** (*byte string*) -- - (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, - and ``MODE_OPENPGP`` modes). - - The initialization vector to use for encryption or decryption. - - For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. - - For ``MODE_OPENPGP`` mode only, - it must be 8 bytes long for encryption - and 10 bytes for decryption (in the latter case, it is - actually the *encrypted* IV which was prefixed to the ciphertext). - - If not provided, a random byte string is generated (you must then - read its value with the :attr:`iv` attribute). - - * **nonce** (*byte string*) -- - (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). - - A value that must never be reused for any other encryption done - with this key. - - For ``MODE_EAX`` there are no - restrictions on its length (recommended: **16** bytes). - - For ``MODE_CTR``, its length must be in the range **[0..7]**. - - If not provided for ``MODE_EAX``, a random byte string is generated (you - can read it back via the ``nonce`` attribute). - - * **segment_size** (*integer*) -- - (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext - are segmented in. It must be a multiple of 8. - If not specified, it will be assumed to be 8. - - * **mac_len** : (*integer*) -- - (Only ``MODE_EAX``) - Length of the authentication tag, in bytes. - It must be no longer than 8 (default). - - * **initial_value** : (*integer*) -- - (Only ``MODE_CTR``). The initial value for the counter within - the counter block. By default it is **0**. - - :Return: a DES object, of the applicable mode. - """ - - return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) - -MODE_ECB = 1 -MODE_CBC = 2 -MODE_CFB = 3 -MODE_OFB = 5 -MODE_CTR = 6 -MODE_OPENPGP = 7 -MODE_EAX = 9 - -# Size of a data block (in bytes) -block_size = 8 -# Size of a key (in bytes) -key_size = 8 diff --git a/Crypto/Cipher/DES.pyi b/Crypto/Cipher/DES.pyi deleted file mode 100644 index 1047f13..0000000 --- a/Crypto/Cipher/DES.pyi +++ /dev/null @@ -1,35 +0,0 @@ -from typing import Union, Dict, Iterable - -from Crypto.Cipher._mode_ecb import EcbMode -from Crypto.Cipher._mode_cbc import CbcMode -from Crypto.Cipher._mode_cfb import CfbMode -from Crypto.Cipher._mode_ofb import OfbMode -from Crypto.Cipher._mode_ctr import CtrMode -from Crypto.Cipher._mode_openpgp import OpenPgpMode -from Crypto.Cipher._mode_eax import EaxMode - -DESMode = int - -MODE_ECB: DESMode -MODE_CBC: DESMode -MODE_CFB: DESMode -MODE_OFB: DESMode -MODE_CTR: DESMode -MODE_OPENPGP: DESMode -MODE_EAX: DESMode - -Buffer = Union[bytes, bytearray, memoryview] - -def new(key: Buffer, - mode: DESMode, - iv : Buffer = ..., - IV : Buffer = ..., - nonce : Buffer = ..., - segment_size : int = ..., - mac_len : int = ..., - initial_value : Union[int, Buffer] = ..., - counter : Dict = ...) -> \ - Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... - -block_size: int -key_size: int diff --git a/Crypto/Cipher/DES3.py b/Crypto/Cipher/DES3.py deleted file mode 100644 index c0d9367..0000000 --- a/Crypto/Cipher/DES3.py +++ /dev/null @@ -1,187 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Cipher/DES3.py : DES3 -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== -""" -Module's constants for the modes of operation supported with Triple DES: - -:var MODE_ECB: :ref:`Electronic Code Book (ECB) ` -:var MODE_CBC: :ref:`Cipher-Block Chaining (CBC) ` -:var MODE_CFB: :ref:`Cipher FeedBack (CFB) ` -:var MODE_OFB: :ref:`Output FeedBack (OFB) ` -:var MODE_CTR: :ref:`CounTer Mode (CTR) ` -:var MODE_OPENPGP: :ref:`OpenPGP Mode ` -:var MODE_EAX: :ref:`EAX Mode ` -""" - -import sys - -from Crypto.Cipher import _create_cipher -from Crypto.Util.py3compat import byte_string, bchr, bord, bstr -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - c_size_t) - -_raw_des3_lib = load_pycryptodome_raw_lib( - "Crypto.Cipher._raw_des3", - """ - int DES3_start_operation(const uint8_t key[], - size_t key_len, - void **pResult); - int DES3_encrypt(const void *state, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int DES3_decrypt(const void *state, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int DES3_stop_operation(void *state); - """) - - -def adjust_key_parity(key_in): - """Set the parity bits in a TDES key. - - :param key_in: the TDES key whose bits need to be adjusted - :type key_in: byte string - - :returns: a copy of ``key_in``, with the parity bits correctly set - :rtype: byte string - - :raises ValueError: if the TDES key is not 16 or 24 bytes long - :raises ValueError: if the TDES key degenerates into Single DES - """ - - def parity_byte(key_byte): - parity = 1 - for i in range(1, 8): - parity ^= (key_byte >> i) & 1 - return (key_byte & 0xFE) | parity - - if len(key_in) not in key_size: - raise ValueError("Not a valid TDES key") - - key_out = b"".join([ bchr(parity_byte(bord(x))) for x in key_in ]) - - if key_out[:8] == key_out[8:16] or key_out[-16:-8] == key_out[-8:]: - raise ValueError("Triple DES key degenerates to single DES") - - return key_out - - -def _create_base_cipher(dict_parameters): - """This method instantiates and returns a handle to a low-level base cipher. - It will absorb named parameters in the process.""" - - try: - key_in = dict_parameters.pop("key") - except KeyError: - raise TypeError("Missing 'key' parameter") - - key = adjust_key_parity(bstr(key_in)) - - start_operation = _raw_des3_lib.DES3_start_operation - stop_operation = _raw_des3_lib.DES3_stop_operation - - cipher = VoidPointer() - result = start_operation(key, - c_size_t(len(key)), - cipher.address_of()) - if result: - raise ValueError("Error %X while instantiating the TDES cipher" - % result) - return SmartPointer(cipher.get(), stop_operation) - - -def new(key, mode, *args, **kwargs): - """Create a new Triple DES cipher. - - :param key: - The secret key to use in the symmetric cipher. - It must be 16 or 24 byte long. The parity bits will be ignored. - :type key: bytes/bytearray/memoryview - - :param mode: - The chaining mode to use for encryption or decryption. - :type mode: One of the supported ``MODE_*`` constants - - :Keyword Arguments: - * **iv** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``, - and ``MODE_OPENPGP`` modes). - - The initialization vector to use for encryption or decryption. - - For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 8 bytes long. - - For ``MODE_OPENPGP`` mode only, - it must be 8 bytes long for encryption - and 10 bytes for decryption (in the latter case, it is - actually the *encrypted* IV which was prefixed to the ciphertext). - - If not provided, a random byte string is generated (you must then - read its value with the :attr:`iv` attribute). - - * **nonce** (*bytes*, *bytearray*, *memoryview*) -- - (Only applicable for ``MODE_EAX`` and ``MODE_CTR``). - - A value that must never be reused for any other encryption done - with this key. - - For ``MODE_EAX`` there are no - restrictions on its length (recommended: **16** bytes). - - For ``MODE_CTR``, its length must be in the range **[0..7]**. - - If not provided for ``MODE_EAX``, a random byte string is generated (you - can read it back via the ``nonce`` attribute). - - * **segment_size** (*integer*) -- - (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext - are segmented in. It must be a multiple of 8. - If not specified, it will be assumed to be 8. - - * **mac_len** : (*integer*) -- - (Only ``MODE_EAX``) - Length of the authentication tag, in bytes. - It must be no longer than 8 (default). - - * **initial_value** : (*integer*) -- - (Only ``MODE_CTR``). The initial value for the counter within - the counter block. By default it is **0**. - - :Return: a Triple DES object, of the applicable mode. - """ - - return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs) - -MODE_ECB = 1 -MODE_CBC = 2 -MODE_CFB = 3 -MODE_OFB = 5 -MODE_CTR = 6 -MODE_OPENPGP = 7 -MODE_EAX = 9 - -# Size of a data block (in bytes) -block_size = 8 -# Size of a key (in bytes) -key_size = (16, 24) diff --git a/Crypto/Cipher/DES3.pyi b/Crypto/Cipher/DES3.pyi deleted file mode 100644 index a89db9c..0000000 --- a/Crypto/Cipher/DES3.pyi +++ /dev/null @@ -1,37 +0,0 @@ -from typing import Union, Dict, Tuple - -from Crypto.Cipher._mode_ecb import EcbMode -from Crypto.Cipher._mode_cbc import CbcMode -from Crypto.Cipher._mode_cfb import CfbMode -from Crypto.Cipher._mode_ofb import OfbMode -from Crypto.Cipher._mode_ctr import CtrMode -from Crypto.Cipher._mode_openpgp import OpenPgpMode -from Crypto.Cipher._mode_eax import EaxMode - -def adjust_key_parity(key_in: bytes) -> bytes: ... - -DES3Mode = int - -MODE_ECB: DES3Mode -MODE_CBC: DES3Mode -MODE_CFB: DES3Mode -MODE_OFB: DES3Mode -MODE_CTR: DES3Mode -MODE_OPENPGP: DES3Mode -MODE_EAX: DES3Mode - -Buffer = Union[bytes, bytearray, memoryview] - -def new(key: Buffer, - mode: DES3Mode, - iv : Buffer = ..., - IV : Buffer = ..., - nonce : Buffer = ..., - segment_size : int = ..., - mac_len : int = ..., - initial_value : Union[int, Buffer] = ..., - counter : Dict = ...) -> \ - Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ... - -block_size: int -key_size: Tuple[int, int] diff --git a/Crypto/Cipher/PKCS1_OAEP.py b/Crypto/Cipher/PKCS1_OAEP.py deleted file mode 100644 index 4fdf76d..0000000 --- a/Crypto/Cipher/PKCS1_OAEP.py +++ /dev/null @@ -1,239 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Cipher/PKCS1_OAEP.py : PKCS#1 OAEP -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -from Crypto.Signature.pss import MGF1 -import Crypto.Hash.SHA1 - -from Crypto.Util.py3compat import bord, _copy_bytes -import Crypto.Util.number -from Crypto.Util.number import ceil_div, bytes_to_long, long_to_bytes -from Crypto.Util.strxor import strxor -from Crypto import Random - -class PKCS1OAEP_Cipher: - """Cipher object for PKCS#1 v1.5 OAEP. - Do not create directly: use :func:`new` instead.""" - - def __init__(self, key, hashAlgo, mgfunc, label, randfunc): - """Initialize this PKCS#1 OAEP cipher object. - - :Parameters: - key : an RSA key object - If a private half is given, both encryption and decryption are possible. - If a public half is given, only encryption is possible. - hashAlgo : hash object - The hash function to use. This can be a module under `Crypto.Hash` - or an existing hash object created from any of such modules. If not specified, - `Crypto.Hash.SHA1` is used. - mgfunc : callable - A mask generation function that accepts two parameters: a string to - use as seed, and the lenth of the mask to generate, in bytes. - If not specified, the standard MGF1 consistent with ``hashAlgo`` is used (a safe choice). - label : bytes/bytearray/memoryview - A label to apply to this particular encryption. If not specified, - an empty string is used. Specifying a label does not improve - security. - randfunc : callable - A function that returns random bytes. - - :attention: Modify the mask generation function only if you know what you are doing. - Sender and receiver must use the same one. - """ - self._key = key - - if hashAlgo: - self._hashObj = hashAlgo - else: - self._hashObj = Crypto.Hash.SHA1 - - if mgfunc: - self._mgf = mgfunc - else: - self._mgf = lambda x,y: MGF1(x,y,self._hashObj) - - self._label = _copy_bytes(None, None, label) - self._randfunc = randfunc - - def can_encrypt(self): - """Legacy function to check if you can call :meth:`encrypt`. - - .. deprecated:: 3.0""" - return self._key.can_encrypt() - - def can_decrypt(self): - """Legacy function to check if you can call :meth:`decrypt`. - - .. deprecated:: 3.0""" - return self._key.can_decrypt() - - def encrypt(self, message): - """Encrypt a message with PKCS#1 OAEP. - - :param message: - The message to encrypt, also known as plaintext. It can be of - variable length, but not longer than the RSA modulus (in bytes) - minus 2, minus twice the hash output size. - For instance, if you use RSA 2048 and SHA-256, the longest message - you can encrypt is 190 byte long. - :type message: bytes/bytearray/memoryview - - :returns: The ciphertext, as large as the RSA modulus. - :rtype: bytes - - :raises ValueError: - if the message is too long. - """ - - # See 7.1.1 in RFC3447 - modBits = Crypto.Util.number.size(self._key.n) - k = ceil_div(modBits, 8) # Convert from bits to bytes - hLen = self._hashObj.digest_size - mLen = len(message) - - # Step 1b - ps_len = k - mLen - 2 * hLen - 2 - if ps_len < 0: - raise ValueError("Plaintext is too long.") - # Step 2a - lHash = self._hashObj.new(self._label).digest() - # Step 2b - ps = b'\x00' * ps_len - # Step 2c - db = lHash + ps + b'\x01' + _copy_bytes(None, None, message) - # Step 2d - ros = self._randfunc(hLen) - # Step 2e - dbMask = self._mgf(ros, k-hLen-1) - # Step 2f - maskedDB = strxor(db, dbMask) - # Step 2g - seedMask = self._mgf(maskedDB, hLen) - # Step 2h - maskedSeed = strxor(ros, seedMask) - # Step 2i - em = b'\x00' + maskedSeed + maskedDB - # Step 3a (OS2IP) - em_int = bytes_to_long(em) - # Step 3b (RSAEP) - m_int = self._key._encrypt(em_int) - # Step 3c (I2OSP) - c = long_to_bytes(m_int, k) - return c - - def decrypt(self, ciphertext): - """Decrypt a message with PKCS#1 OAEP. - - :param ciphertext: The encrypted message. - :type ciphertext: bytes/bytearray/memoryview - - :returns: The original message (plaintext). - :rtype: bytes - - :raises ValueError: - if the ciphertext has the wrong length, or if decryption - fails the integrity check (in which case, the decryption - key is probably wrong). - :raises TypeError: - if the RSA key has no private half (i.e. you are trying - to decrypt using a public key). - """ - - # See 7.1.2 in RFC3447 - modBits = Crypto.Util.number.size(self._key.n) - k = ceil_div(modBits,8) # Convert from bits to bytes - hLen = self._hashObj.digest_size - - # Step 1b and 1c - if len(ciphertext) != k or k Any: ... - -class HashLikeModule(Protocol): - digest_size : int - @staticmethod - def new(data: Optional[bytes] = ...) -> Any: ... - -HashLike = Union[HashLikeClass, HashLikeModule] - -Buffer = Union[bytes, bytearray, memoryview] - -class PKCS1OAEP_Cipher: - def __init__(self, - key: RsaKey, - hashAlgo: HashLike, - mgfunc: Callable[[bytes, int], bytes], - label: Buffer, - randfunc: Callable[[int], bytes]) -> None: ... - def can_encrypt(self) -> bool: ... - def can_decrypt(self) -> bool: ... - def encrypt(self, message: Buffer) -> bytes: ... - def decrypt(self, ciphertext: Buffer) -> bytes: ... - -def new(key: RsaKey, - hashAlgo: Optional[HashLike] = ..., - mgfunc: Optional[Callable[[bytes, int], bytes]] = ..., - label: Optional[Buffer] = ..., - randfunc: Optional[Callable[[int], bytes]] = ...) -> PKCS1OAEP_Cipher: ... diff --git a/Crypto/Cipher/PKCS1_v1_5.py b/Crypto/Cipher/PKCS1_v1_5.py deleted file mode 100644 index 1b9912f..0000000 --- a/Crypto/Cipher/PKCS1_v1_5.py +++ /dev/null @@ -1,199 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Cipher/PKCS1-v1_5.py : PKCS#1 v1.5 -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -__all__ = [ 'new', 'PKCS115_Cipher' ] - -from Crypto.Util.number import ceil_div, bytes_to_long, long_to_bytes -from Crypto.Util.py3compat import bord, _copy_bytes -import Crypto.Util.number -from Crypto import Random - -class PKCS115_Cipher: - """This cipher can perform PKCS#1 v1.5 RSA encryption or decryption. - Do not instantiate directly. Use :func:`Crypto.Cipher.PKCS1_v1_5.new` instead.""" - - def __init__(self, key, randfunc): - """Initialize this PKCS#1 v1.5 cipher object. - - :Parameters: - key : an RSA key object - If a private half is given, both encryption and decryption are possible. - If a public half is given, only encryption is possible. - randfunc : callable - Function that returns random bytes. - """ - - self._key = key - self._randfunc = randfunc - - def can_encrypt(self): - """Return True if this cipher object can be used for encryption.""" - return self._key.can_encrypt() - - def can_decrypt(self): - """Return True if this cipher object can be used for decryption.""" - return self._key.can_decrypt() - - def encrypt(self, message): - """Produce the PKCS#1 v1.5 encryption of a message. - - This function is named ``RSAES-PKCS1-V1_5-ENCRYPT``, and it is specified in - `section 7.2.1 of RFC8017 - `_. - - :param message: - The message to encrypt, also known as plaintext. It can be of - variable length, but not longer than the RSA modulus (in bytes) minus 11. - :type message: bytes/bytearray/memoryview - - :Returns: A byte string, the ciphertext in which the message is encrypted. - It is as long as the RSA modulus (in bytes). - - :Raises ValueError: - If the RSA key length is not sufficiently long to deal with the given - message. - """ - - # See 7.2.1 in RFC8017 - modBits = Crypto.Util.number.size(self._key.n) - k = ceil_div(modBits,8) # Convert from bits to bytes - mLen = len(message) - - # Step 1 - if mLen > k - 11: - raise ValueError("Plaintext is too long.") - # Step 2a - ps = [] - while len(ps) != k - mLen - 3: - new_byte = self._randfunc(1) - if bord(new_byte[0]) == 0x00: - continue - ps.append(new_byte) - ps = b"".join(ps) - assert(len(ps) == k - mLen - 3) - # Step 2b - em = b'\x00\x02' + ps + b'\x00' + _copy_bytes(None, None, message) - # Step 3a (OS2IP) - em_int = bytes_to_long(em) - # Step 3b (RSAEP) - m_int = self._key._encrypt(em_int) - # Step 3c (I2OSP) - c = long_to_bytes(m_int, k) - return c - - def decrypt(self, ciphertext, sentinel): - r"""Decrypt a PKCS#1 v1.5 ciphertext. - - This function is named ``RSAES-PKCS1-V1_5-DECRYPT``, and is specified in - `section 7.2.2 of RFC8017 - `_. - - :param ciphertext: - The ciphertext that contains the message to recover. - :type ciphertext: bytes/bytearray/memoryview - - :param sentinel: - The object to return whenever an error is detected. - :type sentinel: any type - - :Returns: A byte string. It is either the original message or the ``sentinel`` (in case of an error). - - :Raises ValueError: - If the ciphertext length is incorrect - :Raises TypeError: - If the RSA key has no private half (i.e. it cannot be used for - decyption). - - .. warning:: - You should **never** let the party who submitted the ciphertext know that - this function returned the ``sentinel`` value. - Armed with such knowledge (for a fair amount of carefully crafted but invalid ciphertexts), - an attacker is able to recontruct the plaintext of any other encryption that were carried out - with the same RSA public key (see `Bleichenbacher's`__ attack). - - In general, it should not be possible for the other party to distinguish - whether processing at the server side failed because the value returned - was a ``sentinel`` as opposed to a random, invalid message. - - In fact, the second option is not that unlikely: encryption done according to PKCS#1 v1.5 - embeds no good integrity check. There is roughly one chance - in 2\ :sup:`16` for a random ciphertext to be returned as a valid message - (although random looking). - - It is therefore advisabled to: - - 1. Select as ``sentinel`` a value that resembles a plausable random, invalid message. - 2. Not report back an error as soon as you detect a ``sentinel`` value. - Put differently, you should not explicitly check if the returned value is the ``sentinel`` or not. - 3. Cover all possible errors with a single, generic error indicator. - 4. Embed into the definition of ``message`` (at the protocol level) a digest (e.g. ``SHA-1``). - It is recommended for it to be the rightmost part ``message``. - 5. Where possible, monitor the number of errors due to ciphertexts originating from the same party, - and slow down the rate of the requests from such party (or even blacklist it altogether). - - **If you are designing a new protocol, consider using the more robust PKCS#1 OAEP.** - - .. __: http://www.bell-labs.com/user/bleichen/papers/pkcs.ps - - """ - - # See 7.2.1 in RFC3447 - modBits = Crypto.Util.number.size(self._key.n) - k = ceil_div(modBits,8) # Convert from bits to bytes - - # Step 1 - if len(ciphertext) != k: - raise ValueError("Ciphertext with incorrect length.") - # Step 2a (O2SIP) - ct_int = bytes_to_long(ciphertext) - # Step 2b (RSADP) - m_int = self._key._decrypt(ct_int) - # Complete step 2c (I2OSP) - em = long_to_bytes(m_int, k) - # Step 3 - sep = em.find(b'\x00', 2) - if not em.startswith(b'\x00\x02') or sep < 10: - return sentinel - # Step 4 - return em[sep + 1:] - - -def new(key, randfunc=None): - """Create a cipher for performing PKCS#1 v1.5 encryption or decryption. - - :param key: - The key to use to encrypt or decrypt the message. This is a `Crypto.PublicKey.RSA` object. - Decryption is only possible if *key* is a private RSA key. - :type key: RSA key object - - :param randfunc: - Function that return random bytes. - The default is :func:`Crypto.Random.get_random_bytes`. - :type randfunc: callable - - :returns: A cipher object `PKCS115_Cipher`. - """ - - if randfunc is None: - randfunc = Random.get_random_bytes - return PKCS115_Cipher(key, randfunc) - diff --git a/Crypto/Cipher/PKCS1_v1_5.pyi b/Crypto/Cipher/PKCS1_v1_5.pyi deleted file mode 100644 index d640736..0000000 --- a/Crypto/Cipher/PKCS1_v1_5.pyi +++ /dev/null @@ -1,17 +0,0 @@ -from typing import Callable, Union, Any, Optional - -from Crypto.PublicKey.RSA import RsaKey - -Buffer = Union[bytes, bytearray, memoryview] - -class PKCS115_Cipher: - def __init__(self, - key: RsaKey, - randfunc: Callable[[int], bytes]) -> None: ... - def can_encrypt(self) -> bool: ... - def can_decrypt(self) -> bool: ... - def encrypt(self, message: Buffer) -> bytes: ... - def decrypt(self, ciphertext: Buffer, sentinel: Buffer) -> bytes: ... - -def new(key: RsaKey, - randfunc: Optional[Callable[[int], bytes]] = ...) -> PKCS115_Cipher: ... diff --git a/Crypto/Cipher/Salsa20.py b/Crypto/Cipher/Salsa20.py deleted file mode 100644 index 62d0b29..0000000 --- a/Crypto/Cipher/Salsa20.py +++ /dev/null @@ -1,167 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Cipher/Salsa20.py : Salsa20 stream cipher (http://cr.yp.to/snuffle.html) -# -# Contributed by Fabrizio Tarizzo . -# -# =================================================================== -# 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 Crypto.Util.py3compat import _copy_bytes -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - create_string_buffer, - get_raw_buffer, VoidPointer, - SmartPointer, c_size_t, - c_uint8_ptr, is_writeable_buffer) - -from Crypto.Random import get_random_bytes - -_raw_salsa20_lib = load_pycryptodome_raw_lib("Crypto.Cipher._Salsa20", - """ - int Salsa20_stream_init(uint8_t *key, size_t keylen, - uint8_t *nonce, size_t nonce_len, - void **pSalsaState); - int Salsa20_stream_destroy(void *salsaState); - int Salsa20_stream_encrypt(void *salsaState, - const uint8_t in[], - uint8_t out[], size_t len); - """) - - -class Salsa20Cipher: - """Salsa20 cipher object. Do not create it directly. Use :py:func:`new` - instead. - - :var nonce: The nonce with length 8 - :vartype nonce: byte string - """ - - def __init__(self, key, nonce): - """Initialize a Salsa20 cipher object - - See also `new()` at the module level.""" - - if len(key) not in key_size: - raise ValueError("Incorrect key length for Salsa20 (%d bytes)" % len(key)) - - if len(nonce) != 8: - raise ValueError("Incorrect nonce length for Salsa20 (%d bytes)" % - len(nonce)) - - self.nonce = _copy_bytes(None, None, nonce) - - self._state = VoidPointer() - result = _raw_salsa20_lib.Salsa20_stream_init( - c_uint8_ptr(key), - c_size_t(len(key)), - c_uint8_ptr(nonce), - c_size_t(len(nonce)), - self._state.address_of()) - if result: - raise ValueError("Error %d instantiating a Salsa20 cipher") - self._state = SmartPointer(self._state.get(), - _raw_salsa20_lib.Salsa20_stream_destroy) - - self.block_size = 1 - self.key_size = len(key) - - def encrypt(self, plaintext, output=None): - """Encrypt a piece of data. - - Args: - plaintext(bytes/bytearray/memoryview): The data to encrypt, of any size. - Keyword Args: - output(bytes/bytearray/memoryview): The location where the ciphertext - is written to. If ``None``, the ciphertext is returned. - Returns: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if output is None: - ciphertext = create_string_buffer(len(plaintext)) - else: - ciphertext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(plaintext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = _raw_salsa20_lib.Salsa20_stream_encrypt( - self._state.get(), - c_uint8_ptr(plaintext), - c_uint8_ptr(ciphertext), - c_size_t(len(plaintext))) - if result: - raise ValueError("Error %d while encrypting with Salsa20" % result) - - if output is None: - return get_raw_buffer(ciphertext) - else: - return None - - def decrypt(self, ciphertext, output=None): - """Decrypt a piece of data. - - Args: - ciphertext(bytes/bytearray/memoryview): The data to decrypt, of any size. - Keyword Args: - output(bytes/bytearray/memoryview): The location where the plaintext - is written to. If ``None``, the plaintext is returned. - Returns: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ - - try: - return self.encrypt(ciphertext, output=output) - except ValueError as e: - raise ValueError(str(e).replace("enc", "dec")) - - -def new(key, nonce=None): - """Create a new Salsa20 cipher - - :keyword key: The secret key to use. It must be 16 or 32 bytes long. - :type key: bytes/bytearray/memoryview - - :keyword nonce: - A value that must never be reused for any other encryption - done with this key. It must be 8 bytes long. - - If not provided, a random byte string will be generated (you can read - it back via the ``nonce`` attribute of the returned object). - :type nonce: bytes/bytearray/memoryview - - :Return: a :class:`Crypto.Cipher.Salsa20.Salsa20Cipher` object - """ - - if nonce is None: - nonce = get_random_bytes(8) - - return Salsa20Cipher(key, nonce) - -# Size of a data block (in bytes) -block_size = 1 - -# Size of a key (in bytes) -key_size = (16, 32) - diff --git a/Crypto/Cipher/Salsa20.pyi b/Crypto/Cipher/Salsa20.pyi deleted file mode 100644 index 9178f0d..0000000 --- a/Crypto/Cipher/Salsa20.pyi +++ /dev/null @@ -1,27 +0,0 @@ -from typing import Union, Tuple, Optional, overload - - -Buffer = Union[bytes, bytearray, memoryview] - -class Salsa20Cipher: - nonce: bytes - block_size: int - key_size: int - - def __init__(self, - key: Buffer, - nonce: Buffer) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - -def new(key: Buffer, nonce: Optional[Buffer] = ...) -> Salsa20Cipher: ... - -block_size: int -key_size: Tuple[int, int] - diff --git a/Crypto/Cipher/_ARC4.abi3.so b/Crypto/Cipher/_ARC4.abi3.so deleted file mode 100644 index bc11d1a..0000000 Binary files a/Crypto/Cipher/_ARC4.abi3.so and /dev/null differ diff --git a/Crypto/Cipher/_EKSBlowfish.py b/Crypto/Cipher/_EKSBlowfish.py deleted file mode 100644 index a844fae..0000000 --- a/Crypto/Cipher/_EKSBlowfish.py +++ /dev/null @@ -1,131 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2019, Legrandin -# 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 sys - -from Crypto.Cipher import _create_cipher -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, c_size_t, - c_uint8_ptr, c_uint) - -_raw_blowfish_lib = load_pycryptodome_raw_lib( - "Crypto.Cipher._raw_eksblowfish", - """ - int EKSBlowfish_start_operation(const uint8_t key[], - size_t key_len, - const uint8_t salt[16], - size_t salt_len, - unsigned cost, - unsigned invert, - void **pResult); - int EKSBlowfish_encrypt(const void *state, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int EKSBlowfish_decrypt(const void *state, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int EKSBlowfish_stop_operation(void *state); - """ - ) - - -def _create_base_cipher(dict_parameters): - """This method instantiates and returns a smart pointer to - a low-level base cipher. It will absorb named parameters in - the process.""" - - try: - key = dict_parameters.pop("key") - salt = dict_parameters.pop("salt") - cost = dict_parameters.pop("cost") - except KeyError as e: - raise TypeError("Missing EKSBlowfish parameter: " + str(e)) - invert = dict_parameters.pop("invert", True) - - if len(key) not in key_size: - raise ValueError("Incorrect EKSBlowfish key length (%d bytes)" % len(key)) - - start_operation = _raw_blowfish_lib.EKSBlowfish_start_operation - stop_operation = _raw_blowfish_lib.EKSBlowfish_stop_operation - - void_p = VoidPointer() - result = start_operation(c_uint8_ptr(key), - c_size_t(len(key)), - c_uint8_ptr(salt), - c_size_t(len(salt)), - c_uint(cost), - c_uint(int(invert)), - void_p.address_of()) - if result: - raise ValueError("Error %X while instantiating the EKSBlowfish cipher" - % result) - return SmartPointer(void_p.get(), stop_operation) - - -def new(key, mode, salt, cost, invert): - """Create a new EKSBlowfish cipher - - Args: - - key (bytes, bytearray, memoryview): - The secret key to use in the symmetric cipher. - Its length can vary from 0 to 72 bytes. - - mode (one of the supported ``MODE_*`` constants): - The chaining mode to use for encryption or decryption. - - salt (bytes, bytearray, memoryview): - The salt that bcrypt uses to thwart rainbow table attacks - - cost (integer): - The complexity factor in bcrypt - - invert (bool): - If ``False``, in the inner loop use ``ExpandKey`` first over the salt - and then over the key, as defined in - the `original bcrypt specification `_. - If ``True``, reverse the order, as in the first implementation of - `bcrypt` in OpenBSD. - - :Return: an EKSBlowfish object - """ - - kwargs = { 'salt':salt, 'cost':cost, 'invert':invert } - return _create_cipher(sys.modules[__name__], key, mode, **kwargs) - - -MODE_ECB = 1 - -# Size of a data block (in bytes) -block_size = 8 -# Size of a key (in bytes) -key_size = range(0, 72 + 1) diff --git a/Crypto/Cipher/_EKSBlowfish.pyi b/Crypto/Cipher/_EKSBlowfish.pyi deleted file mode 100644 index 95db379..0000000 --- a/Crypto/Cipher/_EKSBlowfish.pyi +++ /dev/null @@ -1,15 +0,0 @@ -from typing import Union, Iterable - -from Crypto.Cipher._mode_ecb import EcbMode - -MODE_ECB: int - -Buffer = Union[bytes, bytearray, memoryview] - -def new(key: Buffer, - mode: int, - salt: Buffer, - cost: int) -> EcbMode: ... - -block_size: int -key_size: Iterable[int] diff --git a/Crypto/Cipher/_Salsa20.abi3.so b/Crypto/Cipher/_Salsa20.abi3.so deleted file mode 100644 index 2cefcf3..0000000 Binary files a/Crypto/Cipher/_Salsa20.abi3.so and /dev/null differ diff --git a/Crypto/Cipher/__init__.py b/Crypto/Cipher/__init__.py deleted file mode 100644 index ba2d485..0000000 --- a/Crypto/Cipher/__init__.py +++ /dev/null @@ -1,79 +0,0 @@ -# -# A block cipher is instantiated as a combination of: -# 1. A base cipher (such as AES) -# 2. A mode of operation (such as CBC) -# -# Both items are implemented as C modules. -# -# The API of #1 is (replace "AES" with the name of the actual cipher): -# - AES_start_operaion(key) --> base_cipher_state -# - AES_encrypt(base_cipher_state, in, out, length) -# - AES_decrypt(base_cipher_state, in, out, length) -# - AES_stop_operation(base_cipher_state) -# -# Where base_cipher_state is AES_State, a struct with BlockBase (set of -# pointers to encrypt/decrypt/stop) followed by cipher-specific data. -# -# The API of #2 is (replace "CBC" with the name of the actual mode): -# - CBC_start_operation(base_cipher_state) --> mode_state -# - CBC_encrypt(mode_state, in, out, length) -# - CBC_decrypt(mode_state, in, out, length) -# - CBC_stop_operation(mode_state) -# -# where mode_state is a a pointer to base_cipher_state plus mode-specific data. - -import os - -from Crypto.Cipher._mode_ecb import _create_ecb_cipher -from Crypto.Cipher._mode_cbc import _create_cbc_cipher -from Crypto.Cipher._mode_cfb import _create_cfb_cipher -from Crypto.Cipher._mode_ofb import _create_ofb_cipher -from Crypto.Cipher._mode_ctr import _create_ctr_cipher -from Crypto.Cipher._mode_openpgp import _create_openpgp_cipher -from Crypto.Cipher._mode_ccm import _create_ccm_cipher -from Crypto.Cipher._mode_eax import _create_eax_cipher -from Crypto.Cipher._mode_siv import _create_siv_cipher -from Crypto.Cipher._mode_gcm import _create_gcm_cipher -from Crypto.Cipher._mode_ocb import _create_ocb_cipher - -_modes = { 1:_create_ecb_cipher, - 2:_create_cbc_cipher, - 3:_create_cfb_cipher, - 5:_create_ofb_cipher, - 6:_create_ctr_cipher, - 7:_create_openpgp_cipher, - 9:_create_eax_cipher - } - -_extra_modes = { 8:_create_ccm_cipher, - 10:_create_siv_cipher, - 11:_create_gcm_cipher, - 12:_create_ocb_cipher - } - -def _create_cipher(factory, key, mode, *args, **kwargs): - - kwargs["key"] = key - - modes = dict(_modes) - if kwargs.pop("add_aes_modes", False): - modes.update(_extra_modes) - if not mode in modes: - raise ValueError("Mode not supported") - - if args: - if mode in (8, 9, 10, 11, 12): - if len(args) > 1: - raise TypeError("Too many arguments for this mode") - kwargs["nonce"] = args[0] - elif mode in (2, 3, 5, 7): - if len(args) > 1: - raise TypeError("Too many arguments for this mode") - kwargs["IV"] = args[0] - elif mode == 6: - if len(args) > 0: - raise TypeError("Too many arguments for this mode") - elif mode == 1: - raise TypeError("IV is not meaningful for the ECB mode") - - return modes[mode](factory, **kwargs) diff --git a/Crypto/Cipher/__init__.pyi b/Crypto/Cipher/__init__.pyi deleted file mode 100644 index e69de29..0000000 diff --git a/Crypto/Cipher/__pycache__/AES.cpython-36.pyc b/Crypto/Cipher/__pycache__/AES.cpython-36.pyc deleted file mode 100644 index 6eae809..0000000 Binary files a/Crypto/Cipher/__pycache__/AES.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Cipher/__pycache__/__init__.cpython-36.pyc b/Crypto/Cipher/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index 2429e78..0000000 Binary files a/Crypto/Cipher/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Cipher/__pycache__/_mode_cbc.cpython-36.pyc b/Crypto/Cipher/__pycache__/_mode_cbc.cpython-36.pyc deleted file mode 100644 index 1770fcc..0000000 Binary files a/Crypto/Cipher/__pycache__/_mode_cbc.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Cipher/__pycache__/_mode_ccm.cpython-36.pyc b/Crypto/Cipher/__pycache__/_mode_ccm.cpython-36.pyc deleted file mode 100644 index 5ec359f..0000000 Binary files a/Crypto/Cipher/__pycache__/_mode_ccm.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Cipher/__pycache__/_mode_cfb.cpython-36.pyc b/Crypto/Cipher/__pycache__/_mode_cfb.cpython-36.pyc deleted file mode 100644 index f44e3cb..0000000 Binary files a/Crypto/Cipher/__pycache__/_mode_cfb.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Cipher/__pycache__/_mode_ctr.cpython-36.pyc b/Crypto/Cipher/__pycache__/_mode_ctr.cpython-36.pyc deleted file mode 100644 index 36986db..0000000 Binary files a/Crypto/Cipher/__pycache__/_mode_ctr.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Cipher/__pycache__/_mode_eax.cpython-36.pyc b/Crypto/Cipher/__pycache__/_mode_eax.cpython-36.pyc deleted file mode 100644 index 937a480..0000000 Binary files a/Crypto/Cipher/__pycache__/_mode_eax.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Cipher/__pycache__/_mode_ecb.cpython-36.pyc b/Crypto/Cipher/__pycache__/_mode_ecb.cpython-36.pyc deleted file mode 100644 index cf48197..0000000 Binary files a/Crypto/Cipher/__pycache__/_mode_ecb.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Cipher/__pycache__/_mode_gcm.cpython-36.pyc b/Crypto/Cipher/__pycache__/_mode_gcm.cpython-36.pyc deleted file mode 100644 index b96de6c..0000000 Binary files a/Crypto/Cipher/__pycache__/_mode_gcm.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Cipher/__pycache__/_mode_ocb.cpython-36.pyc b/Crypto/Cipher/__pycache__/_mode_ocb.cpython-36.pyc deleted file mode 100644 index b63e910..0000000 Binary files a/Crypto/Cipher/__pycache__/_mode_ocb.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Cipher/__pycache__/_mode_ofb.cpython-36.pyc b/Crypto/Cipher/__pycache__/_mode_ofb.cpython-36.pyc deleted file mode 100644 index 173cc0b..0000000 Binary files a/Crypto/Cipher/__pycache__/_mode_ofb.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Cipher/__pycache__/_mode_openpgp.cpython-36.pyc b/Crypto/Cipher/__pycache__/_mode_openpgp.cpython-36.pyc deleted file mode 100644 index 924edc3..0000000 Binary files a/Crypto/Cipher/__pycache__/_mode_openpgp.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Cipher/__pycache__/_mode_siv.cpython-36.pyc b/Crypto/Cipher/__pycache__/_mode_siv.cpython-36.pyc deleted file mode 100644 index ec40a48..0000000 Binary files a/Crypto/Cipher/__pycache__/_mode_siv.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Cipher/_chacha20.abi3.so b/Crypto/Cipher/_chacha20.abi3.so deleted file mode 100644 index f346795..0000000 Binary files a/Crypto/Cipher/_chacha20.abi3.so and /dev/null differ diff --git a/Crypto/Cipher/_mode_cbc.py b/Crypto/Cipher/_mode_cbc.py deleted file mode 100644 index 79c871a..0000000 --- a/Crypto/Cipher/_mode_cbc.py +++ /dev/null @@ -1,293 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -""" -Ciphertext Block Chaining (CBC) mode. -""" - -__all__ = ['CbcMode'] - -from Crypto.Util.py3compat import _copy_bytes -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - create_string_buffer, get_raw_buffer, - SmartPointer, c_size_t, c_uint8_ptr, - is_writeable_buffer) - -from Crypto.Random import get_random_bytes - -raw_cbc_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_cbc", """ - int CBC_start_operation(void *cipher, - const uint8_t iv[], - size_t iv_len, - void **pResult); - int CBC_encrypt(void *cbcState, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int CBC_decrypt(void *cbcState, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int CBC_stop_operation(void *state); - """ - ) - - -class CbcMode(object): - """*Cipher-Block Chaining (CBC)*. - - Each of the ciphertext blocks depends on the current - and all previous plaintext blocks. - - An Initialization Vector (*IV*) is required. - - See `NIST SP800-38A`_ , Section 6.2 . - - .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - - :undocumented: __init__ - """ - - def __init__(self, block_cipher, iv): - """Create a new block cipher, configured in CBC mode. - - :Parameters: - block_cipher : C pointer - A smart pointer to the low-level block cipher instance. - - iv : bytes/bytearray/memoryview - The initialization vector to use for encryption or decryption. - It is as long as the cipher block. - - **The IV must be unpredictable**. Ideally it is picked randomly. - - Reusing the *IV* for encryptions performed with the same key - compromises confidentiality. - """ - - self._state = VoidPointer() - result = raw_cbc_lib.CBC_start_operation(block_cipher.get(), - c_uint8_ptr(iv), - c_size_t(len(iv)), - self._state.address_of()) - if result: - raise ValueError("Error %d while instantiating the CBC mode" - % result) - - # Ensure that object disposal of this Python object will (eventually) - # free the memory allocated by the raw library for the cipher mode - self._state = SmartPointer(self._state.get(), - raw_cbc_lib.CBC_stop_operation) - - # Memory allocated for the underlying block cipher is now owed - # by the cipher mode - block_cipher.release() - - self.block_size = len(iv) - """The block size of the underlying cipher, in bytes.""" - - self.iv = _copy_bytes(None, None, iv) - """The Initialization Vector originally used to create the object. - The value does not change.""" - - self.IV = self.iv - """Alias for `iv`""" - - self._next = [ self.encrypt, self.decrypt ] - - def encrypt(self, plaintext, output=None): - """Encrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. - - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. - - That is, the statement: - - >>> c.encrypt(a) + c.encrypt(b) - - is equivalent to: - - >>> c.encrypt(a+b) - - That also means that you cannot reuse an object for encrypting - or decrypting other data with the same key. - - This function does not add any padding to the plaintext. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - Its lenght must be multiple of the cipher block size. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if self.encrypt not in self._next: - raise TypeError("encrypt() cannot be called after decrypt()") - self._next = [ self.encrypt ] - - if output is None: - ciphertext = create_string_buffer(len(plaintext)) - else: - ciphertext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(plaintext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_cbc_lib.CBC_encrypt(self._state.get(), - c_uint8_ptr(plaintext), - c_uint8_ptr(ciphertext), - c_size_t(len(plaintext))) - if result: - if result == 3: - raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size) - raise ValueError("Error %d while encrypting in CBC mode" % result) - - if output is None: - return get_raw_buffer(ciphertext) - else: - return None - - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. - - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. - - That is, the statement: - - >>> c.decrypt(a) + c.decrypt(b) - - is equivalent to: - - >>> c.decrypt(a+b) - - This function does not remove any padding from the plaintext. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - Its length must be multiple of the cipher block size. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if self.decrypt not in self._next: - raise TypeError("decrypt() cannot be called after encrypt()") - self._next = [ self.decrypt ] - - if output is None: - plaintext = create_string_buffer(len(ciphertext)) - else: - plaintext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(ciphertext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_cbc_lib.CBC_decrypt(self._state.get(), - c_uint8_ptr(ciphertext), - c_uint8_ptr(plaintext), - c_size_t(len(ciphertext))) - if result: - if result == 3: - raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size) - raise ValueError("Error %d while decrypting in CBC mode" % result) - - if output is None: - return get_raw_buffer(plaintext) - else: - return None - - -def _create_cbc_cipher(factory, **kwargs): - """Instantiate a cipher object that performs CBC encryption/decryption. - - :Parameters: - factory : module - The underlying block cipher, a module from ``Crypto.Cipher``. - - :Keywords: - iv : bytes/bytearray/memoryview - The IV to use for CBC. - - IV : bytes/bytearray/memoryview - Alias for ``iv``. - - Any other keyword will be passed to the underlying block cipher. - See the relevant documentation for details (at least ``key`` will need - to be present). - """ - - cipher_state = factory._create_base_cipher(kwargs) - iv = kwargs.pop("IV", None) - IV = kwargs.pop("iv", None) - - if (None, None) == (iv, IV): - iv = get_random_bytes(factory.block_size) - if iv is not None: - if IV is not None: - raise TypeError("You must either use 'iv' or 'IV', not both") - else: - iv = IV - - if len(iv) != factory.block_size: - raise ValueError("Incorrect IV length (it must be %d bytes long)" % - factory.block_size) - - if kwargs: - raise TypeError("Unknown parameters for CBC: %s" % str(kwargs)) - - return CbcMode(cipher_state, iv) diff --git a/Crypto/Cipher/_mode_cbc.pyi b/Crypto/Cipher/_mode_cbc.pyi deleted file mode 100644 index 8b9fb16..0000000 --- a/Crypto/Cipher/_mode_cbc.pyi +++ /dev/null @@ -1,25 +0,0 @@ -from typing import Union, overload - -from Crypto.Util._raw_api import SmartPointer - -Buffer = Union[bytes, bytearray, memoryview] - -__all__ = ['CbcMode'] - -class CbcMode(object): - block_size: int - iv: Buffer - IV: Buffer - - def __init__(self, - block_cipher: SmartPointer, - iv: Buffer) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - diff --git a/Crypto/Cipher/_mode_ccm.py b/Crypto/Cipher/_mode_ccm.py deleted file mode 100644 index 64077de..0000000 --- a/Crypto/Cipher/_mode_ccm.py +++ /dev/null @@ -1,650 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -""" -Counter with CBC-MAC (CCM) mode. -""" - -__all__ = ['CcmMode'] - -import struct -from binascii import unhexlify - -from Crypto.Util.py3compat import (byte_string, bord, - _copy_bytes) -from Crypto.Util._raw_api import is_writeable_buffer - -from Crypto.Util.strxor import strxor -from Crypto.Util.number import long_to_bytes - -from Crypto.Hash import BLAKE2s -from Crypto.Random import get_random_bytes - - -def enum(**enums): - return type('Enum', (), enums) - -MacStatus = enum(NOT_STARTED=0, PROCESSING_AUTH_DATA=1, PROCESSING_PLAINTEXT=2) - - -class CcmMode(object): - """Counter with CBC-MAC (CCM). - - This is an Authenticated Encryption with Associated Data (`AEAD`_) mode. - It provides both confidentiality and authenticity. - - The header of the message may be left in the clear, if needed, and it will - still be subject to authentication. The decryption step tells the receiver - if the message comes from a source that really knowns the secret key. - Additionally, decryption detects if any part of the message - including the - header - has been modified or corrupted. - - This mode requires a nonce. The nonce shall never repeat for two - different messages encrypted with the same key, but it does not need - to be random. - Note that there is a trade-off between the size of the nonce and the - maximum size of a single message you can encrypt. - - It is important to use a large nonce if the key is reused across several - messages and the nonce is chosen randomly. - - It is acceptable to us a short nonce if the key is only used a few times or - if the nonce is taken from a counter. - - The following table shows the trade-off when the nonce is chosen at - random. The column on the left shows how many messages it takes - for the keystream to repeat **on average**. In practice, you will want to - stop using the key way before that. - - +--------------------+---------------+-------------------+ - | Avg. # of messages | nonce | Max. message | - | before keystream | size | size | - | repeats | (bytes) | (bytes) | - +====================+===============+===================+ - | 2^52 | 13 | 64K | - +--------------------+---------------+-------------------+ - | 2^48 | 12 | 16M | - +--------------------+---------------+-------------------+ - | 2^44 | 11 | 4G | - +--------------------+---------------+-------------------+ - | 2^40 | 10 | 1T | - +--------------------+---------------+-------------------+ - | 2^36 | 9 | 64P | - +--------------------+---------------+-------------------+ - | 2^32 | 8 | 16E | - +--------------------+---------------+-------------------+ - - This mode is only available for ciphers that operate on 128 bits blocks - (e.g. AES but not TDES). - - See `NIST SP800-38C`_ or RFC3610_. - - .. _`NIST SP800-38C`: http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C.pdf - .. _RFC3610: https://tools.ietf.org/html/rfc3610 - .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html - - :undocumented: __init__ - """ - - def __init__(self, factory, key, nonce, mac_len, msg_len, assoc_len, - cipher_params): - - self.block_size = factory.block_size - """The block size of the underlying cipher, in bytes.""" - - self.nonce = _copy_bytes(None, None, nonce) - """The nonce used for this cipher instance""" - - self._factory = factory - self._key = _copy_bytes(None, None, key) - self._mac_len = mac_len - self._msg_len = msg_len - self._assoc_len = assoc_len - self._cipher_params = cipher_params - - self._mac_tag = None # Cache for MAC tag - - if self.block_size != 16: - raise ValueError("CCM mode is only available for ciphers" - " that operate on 128 bits blocks") - - # MAC tag length (Tlen) - if mac_len not in (4, 6, 8, 10, 12, 14, 16): - raise ValueError("Parameter 'mac_len' must be even" - " and in the range 4..16 (not %d)" % mac_len) - - # Nonce value - if not (nonce and 7 <= len(nonce) <= 13): - raise ValueError("Length of parameter 'nonce' must be" - " in the range 7..13 bytes") - - # Create MAC object (the tag will be the last block - # bytes worth of ciphertext) - self._mac = self._factory.new(key, - factory.MODE_CBC, - iv=b'\x00' * 16, - **cipher_params) - self._mac_status = MacStatus.NOT_STARTED - self._t = None - - # Allowed transitions after initialization - self._next = [self.update, self.encrypt, self.decrypt, - self.digest, self.verify] - - # Cumulative lengths - self._cumul_assoc_len = 0 - self._cumul_msg_len = 0 - - # Cache for unaligned associated data/plaintext. - # This is a list with byte strings, but when the MAC starts, - # it will become a binary string no longer than the block size. - self._cache = [] - - # Start CTR cipher, by formatting the counter (A.3) - q = 15 - len(nonce) # length of Q, the encoded message length - self._cipher = self._factory.new(key, - self._factory.MODE_CTR, - nonce=struct.pack("B", q - 1) + self.nonce, - **cipher_params) - - # S_0, step 6 in 6.1 for j=0 - self._s_0 = self._cipher.encrypt(b'\x00' * 16) - - # Try to start the MAC - if None not in (assoc_len, msg_len): - self._start_mac() - - def _start_mac(self): - - assert(self._mac_status == MacStatus.NOT_STARTED) - assert(None not in (self._assoc_len, self._msg_len)) - assert(isinstance(self._cache, list)) - - # Formatting control information and nonce (A.2.1) - q = 15 - len(self.nonce) # length of Q, the encoded message length - flags = (64 * (self._assoc_len > 0) + 8 * ((self._mac_len - 2) // 2) + - (q - 1)) - b_0 = struct.pack("B", flags) + self.nonce + long_to_bytes(self._msg_len, q) - - # Formatting associated data (A.2.2) - # Encoded 'a' is concatenated with the associated data 'A' - assoc_len_encoded = b'' - if self._assoc_len > 0: - if self._assoc_len < (2 ** 16 - 2 ** 8): - enc_size = 2 - elif self._assoc_len < (2 ** 32): - assoc_len_encoded = b'\xFF\xFE' - enc_size = 4 - else: - assoc_len_encoded = b'\xFF\xFF' - enc_size = 8 - assoc_len_encoded += long_to_bytes(self._assoc_len, enc_size) - - # b_0 and assoc_len_encoded must be processed first - self._cache.insert(0, b_0) - self._cache.insert(1, assoc_len_encoded) - - # Process all the data cached so far - first_data_to_mac = b"".join(self._cache) - self._cache = b"" - self._mac_status = MacStatus.PROCESSING_AUTH_DATA - self._update(first_data_to_mac) - - def _pad_cache_and_update(self): - - assert(self._mac_status != MacStatus.NOT_STARTED) - assert(len(self._cache) < self.block_size) - - # Associated data is concatenated with the least number - # of zero bytes (possibly none) to reach alignment to - # the 16 byte boundary (A.2.3) - len_cache = len(self._cache) - if len_cache > 0: - self._update(b'\x00' * (self.block_size - len_cache)) - - def update(self, assoc_data): - """Protect associated data - - If there is any associated data, the caller has to invoke - this function one or more times, before using - ``decrypt`` or ``encrypt``. - - By *associated data* it is meant any data (e.g. packet headers) that - will not be encrypted and will be transmitted in the clear. - However, the receiver is still able to detect any modification to it. - In CCM, the *associated data* is also called - *additional authenticated data* (AAD). - - If there is no associated data, this method must not be called. - - The caller may split associated data in segments of any size, and - invoke this method multiple times, each time with the next segment. - - :Parameters: - assoc_data : bytes/bytearray/memoryview - A piece of associated data. There are no restrictions on its size. - """ - - if self.update not in self._next: - raise TypeError("update() can only be called" - " immediately after initialization") - - self._next = [self.update, self.encrypt, self.decrypt, - self.digest, self.verify] - - self._cumul_assoc_len += len(assoc_data) - if self._assoc_len is not None and \ - self._cumul_assoc_len > self._assoc_len: - raise ValueError("Associated data is too long") - - self._update(assoc_data) - return self - - def _update(self, assoc_data_pt=b""): - """Update the MAC with associated data or plaintext - (without FSM checks)""" - - # If MAC has not started yet, we just park the data into a list. - # If the data is mutable, we create a copy and store that instead. - if self._mac_status == MacStatus.NOT_STARTED: - if is_writeable_buffer(assoc_data_pt): - assoc_data_pt = _copy_bytes(None, None, assoc_data_pt) - self._cache.append(assoc_data_pt) - return - - assert(len(self._cache) < self.block_size) - - if len(self._cache) > 0: - filler = min(self.block_size - len(self._cache), - len(assoc_data_pt)) - self._cache += _copy_bytes(None, filler, assoc_data_pt) - assoc_data_pt = _copy_bytes(filler, None, assoc_data_pt) - - if len(self._cache) < self.block_size: - return - - # The cache is exactly one block - self._t = self._mac.encrypt(self._cache) - self._cache = b"" - - update_len = len(assoc_data_pt) // self.block_size * self.block_size - self._cache = _copy_bytes(update_len, None, assoc_data_pt) - if update_len > 0: - self._t = self._mac.encrypt(assoc_data_pt[:update_len])[-16:] - - def encrypt(self, plaintext, output=None): - """Encrypt data with the key set at initialization. - - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. - - This method can be called only **once** if ``msg_len`` was - not passed at initialization. - - If ``msg_len`` was given, the data to encrypt can be broken - up in two or more pieces and `encrypt` can be called - multiple times. - - That is, the statement: - - >>> c.encrypt(a) + c.encrypt(b) - - is equivalent to: - - >>> c.encrypt(a+b) - - This function does not add any padding to the plaintext. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext as ``bytes``. - Otherwise, ``None``. - """ - - if self.encrypt not in self._next: - raise TypeError("encrypt() can only be called after" - " initialization or an update()") - self._next = [self.encrypt, self.digest] - - # No more associated data allowed from now - if self._assoc_len is None: - assert(isinstance(self._cache, list)) - self._assoc_len = sum([len(x) for x in self._cache]) - if self._msg_len is not None: - self._start_mac() - else: - if self._cumul_assoc_len < self._assoc_len: - raise ValueError("Associated data is too short") - - # Only once piece of plaintext accepted if message length was - # not declared in advance - if self._msg_len is None: - self._msg_len = len(plaintext) - self._start_mac() - self._next = [self.digest] - - self._cumul_msg_len += len(plaintext) - if self._cumul_msg_len > self._msg_len: - raise ValueError("Message is too long") - - if self._mac_status == MacStatus.PROCESSING_AUTH_DATA: - # Associated data is concatenated with the least number - # of zero bytes (possibly none) to reach alignment to - # the 16 byte boundary (A.2.3) - self._pad_cache_and_update() - self._mac_status = MacStatus.PROCESSING_PLAINTEXT - - self._update(plaintext) - return self._cipher.encrypt(plaintext, output=output) - - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key set at initialization. - - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. - - This method can be called only **once** if ``msg_len`` was - not passed at initialization. - - If ``msg_len`` was given, the data to decrypt can be - broken up in two or more pieces and `decrypt` can be - called multiple times. - - That is, the statement: - - >>> c.decrypt(a) + c.decrypt(b) - - is equivalent to: - - >>> c.decrypt(a+b) - - This function does not remove any padding from the plaintext. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext as ``bytes``. - Otherwise, ``None``. - """ - - if self.decrypt not in self._next: - raise TypeError("decrypt() can only be called" - " after initialization or an update()") - self._next = [self.decrypt, self.verify] - - # No more associated data allowed from now - if self._assoc_len is None: - assert(isinstance(self._cache, list)) - self._assoc_len = sum([len(x) for x in self._cache]) - if self._msg_len is not None: - self._start_mac() - else: - if self._cumul_assoc_len < self._assoc_len: - raise ValueError("Associated data is too short") - - # Only once piece of ciphertext accepted if message length was - # not declared in advance - if self._msg_len is None: - self._msg_len = len(ciphertext) - self._start_mac() - self._next = [self.verify] - - self._cumul_msg_len += len(ciphertext) - if self._cumul_msg_len > self._msg_len: - raise ValueError("Message is too long") - - if self._mac_status == MacStatus.PROCESSING_AUTH_DATA: - # Associated data is concatenated with the least number - # of zero bytes (possibly none) to reach alignment to - # the 16 byte boundary (A.2.3) - self._pad_cache_and_update() - self._mac_status = MacStatus.PROCESSING_PLAINTEXT - - # Encrypt is equivalent to decrypt with the CTR mode - plaintext = self._cipher.encrypt(ciphertext, output=output) - if output is None: - self._update(plaintext) - else: - self._update(output) - return plaintext - - def digest(self): - """Compute the *binary* MAC tag. - - The caller invokes this function at the very end. - - This method returns the MAC that shall be sent to the receiver, - together with the ciphertext. - - :Return: the MAC, as a byte string. - """ - - if self.digest not in self._next: - raise TypeError("digest() cannot be called when decrypting" - " or validating a message") - self._next = [self.digest] - return self._digest() - - def _digest(self): - if self._mac_tag: - return self._mac_tag - - if self._assoc_len is None: - assert(isinstance(self._cache, list)) - self._assoc_len = sum([len(x) for x in self._cache]) - if self._msg_len is not None: - self._start_mac() - else: - if self._cumul_assoc_len < self._assoc_len: - raise ValueError("Associated data is too short") - - if self._msg_len is None: - self._msg_len = 0 - self._start_mac() - - if self._cumul_msg_len != self._msg_len: - raise ValueError("Message is too short") - - # Both associated data and payload are concatenated with the least - # number of zero bytes (possibly none) that align it to the - # 16 byte boundary (A.2.2 and A.2.3) - self._pad_cache_and_update() - - # Step 8 in 6.1 (T xor MSB_Tlen(S_0)) - self._mac_tag = strxor(self._t, self._s_0)[:self._mac_len] - - return self._mac_tag - - def hexdigest(self): - """Compute the *printable* MAC tag. - - This method is like `digest`. - - :Return: the MAC, as a hexadecimal string. - """ - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def verify(self, received_mac_tag): - """Validate the *binary* MAC tag. - - The caller invokes this function at the very end. - - This method checks if the decrypted message is indeed valid - (that is, if the key is correct) and it has not been - tampered with while in transit. - - :Parameters: - received_mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - if self.verify not in self._next: - raise TypeError("verify() cannot be called" - " when encrypting a message") - self._next = [self.verify] - - self._digest() - secret = get_random_bytes(16) - - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag) - - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") - - def hexverify(self, hex_mac_tag): - """Validate the *printable* MAC tag. - - This method is like `verify`. - - :Parameters: - hex_mac_tag : string - This is the *printable* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - self.verify(unhexlify(hex_mac_tag)) - - def encrypt_and_digest(self, plaintext, output=None): - """Perform encrypt() and digest() in one step. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - a tuple with two items: - - - the ciphertext, as ``bytes`` - - the MAC tag, as ``bytes`` - - The first item becomes ``None`` when the ``output`` parameter - specified a location for the result. - """ - - return self.encrypt(plaintext, output=output), self.digest() - - def decrypt_and_verify(self, ciphertext, received_mac_tag, output=None): - """Perform decrypt() and verify() in one step. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - received_mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: the plaintext as ``bytes`` or ``None`` when the ``output`` - parameter specified a location for the result. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - plaintext = self.decrypt(ciphertext, output=output) - self.verify(received_mac_tag) - return plaintext - - -def _create_ccm_cipher(factory, **kwargs): - """Create a new block cipher, configured in CCM mode. - - :Parameters: - factory : module - A symmetric cipher module from `Crypto.Cipher` (like - `Crypto.Cipher.AES`). - - :Keywords: - key : bytes/bytearray/memoryview - The secret key to use in the symmetric cipher. - - nonce : bytes/bytearray/memoryview - A value that must never be reused for any other encryption. - - Its length must be in the range ``[7..13]``. - 11 or 12 bytes are reasonable values in general. Bear in - mind that with CCM there is a trade-off between nonce length and - maximum message size. - - If not specified, a 11 byte long random string is used. - - mac_len : integer - Length of the MAC, in bytes. It must be even and in - the range ``[4..16]``. The default is 16. - - msg_len : integer - Length of the message to (de)cipher. - If not specified, ``encrypt`` or ``decrypt`` may only be called once. - - assoc_len : integer - Length of the associated data. - If not specified, all data is internally buffered. - """ - - try: - key = key = kwargs.pop("key") - except KeyError as e: - raise TypeError("Missing parameter: " + str(e)) - - nonce = kwargs.pop("nonce", None) # N - if nonce is None: - nonce = get_random_bytes(11) - mac_len = kwargs.pop("mac_len", factory.block_size) - msg_len = kwargs.pop("msg_len", None) # p - assoc_len = kwargs.pop("assoc_len", None) # a - cipher_params = dict(kwargs) - - return CcmMode(factory, key, nonce, mac_len, msg_len, - assoc_len, cipher_params) diff --git a/Crypto/Cipher/_mode_ccm.pyi b/Crypto/Cipher/_mode_ccm.pyi deleted file mode 100644 index 4b9f620..0000000 --- a/Crypto/Cipher/_mode_ccm.pyi +++ /dev/null @@ -1,47 +0,0 @@ -from types import ModuleType -from typing import Union, overload, Dict, Tuple, Optional - -Buffer = Union[bytes, bytearray, memoryview] - -__all__ = ['CcmMode'] - -class CcmMode(object): - block_size: int - nonce: bytes - - def __init__(self, - factory: ModuleType, - key: Buffer, - nonce: Buffer, - mac_len: int, - msg_len: int, - assoc_len: int, - cipher_params: Dict) -> None: ... - - def update(self, assoc_data: Buffer) -> CcmMode: ... - - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, received_mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - - @overload - def encrypt_and_digest(self, - plaintext: Buffer) -> Tuple[bytes, bytes]: ... - @overload - def encrypt_and_digest(self, - plaintext: Buffer, - output: Buffer) -> Tuple[None, bytes]: ... - def decrypt_and_verify(self, - ciphertext: Buffer, - received_mac_tag: Buffer, - output: Optional[Union[bytearray, memoryview]] = ...) -> bytes: ... diff --git a/Crypto/Cipher/_mode_cfb.py b/Crypto/Cipher/_mode_cfb.py deleted file mode 100644 index b3ee1c7..0000000 --- a/Crypto/Cipher/_mode_cfb.py +++ /dev/null @@ -1,293 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Cipher/mode_cfb.py : CFB mode -# -# =================================================================== -# 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. -# =================================================================== - -""" -Counter Feedback (CFB) mode. -""" - -__all__ = ['CfbMode'] - -from Crypto.Util.py3compat import _copy_bytes -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - create_string_buffer, get_raw_buffer, - SmartPointer, c_size_t, c_uint8_ptr, - is_writeable_buffer) - -from Crypto.Random import get_random_bytes - -raw_cfb_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_cfb",""" - int CFB_start_operation(void *cipher, - const uint8_t iv[], - size_t iv_len, - size_t segment_len, /* In bytes */ - void **pResult); - int CFB_encrypt(void *cfbState, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int CFB_decrypt(void *cfbState, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int CFB_stop_operation(void *state);""" - ) - - -class CfbMode(object): - """*Cipher FeedBack (CFB)*. - - This mode is similar to CFB, but it transforms - the underlying block cipher into a stream cipher. - - Plaintext and ciphertext are processed in *segments* - of **s** bits. The mode is therefore sometimes - labelled **s**-bit CFB. - - An Initialization Vector (*IV*) is required. - - See `NIST SP800-38A`_ , Section 6.3. - - .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - - :undocumented: __init__ - """ - - def __init__(self, block_cipher, iv, segment_size): - """Create a new block cipher, configured in CFB mode. - - :Parameters: - block_cipher : C pointer - A smart pointer to the low-level block cipher instance. - - iv : bytes/bytearray/memoryview - The initialization vector to use for encryption or decryption. - It is as long as the cipher block. - - **The IV must be unpredictable**. Ideally it is picked randomly. - - Reusing the *IV* for encryptions performed with the same key - compromises confidentiality. - - segment_size : integer - The number of bytes the plaintext and ciphertext are segmented in. - """ - - self._state = VoidPointer() - result = raw_cfb_lib.CFB_start_operation(block_cipher.get(), - c_uint8_ptr(iv), - c_size_t(len(iv)), - c_size_t(segment_size), - self._state.address_of()) - if result: - raise ValueError("Error %d while instantiating the CFB mode" % result) - - # Ensure that object disposal of this Python object will (eventually) - # free the memory allocated by the raw library for the cipher mode - self._state = SmartPointer(self._state.get(), - raw_cfb_lib.CFB_stop_operation) - - # Memory allocated for the underlying block cipher is now owed - # by the cipher mode - block_cipher.release() - - self.block_size = len(iv) - """The block size of the underlying cipher, in bytes.""" - - self.iv = _copy_bytes(None, None, iv) - """The Initialization Vector originally used to create the object. - The value does not change.""" - - self.IV = self.iv - """Alias for `iv`""" - - self._next = [ self.encrypt, self.decrypt ] - - def encrypt(self, plaintext, output=None): - """Encrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. - - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. - - That is, the statement: - - >>> c.encrypt(a) + c.encrypt(b) - - is equivalent to: - - >>> c.encrypt(a+b) - - This function does not add any padding to the plaintext. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if self.encrypt not in self._next: - raise TypeError("encrypt() cannot be called after decrypt()") - self._next = [ self.encrypt ] - - if output is None: - ciphertext = create_string_buffer(len(plaintext)) - else: - ciphertext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(plaintext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_cfb_lib.CFB_encrypt(self._state.get(), - c_uint8_ptr(plaintext), - c_uint8_ptr(ciphertext), - c_size_t(len(plaintext))) - if result: - raise ValueError("Error %d while encrypting in CFB mode" % result) - - if output is None: - return get_raw_buffer(ciphertext) - else: - return None - - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. - - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. - - That is, the statement: - - >>> c.decrypt(a) + c.decrypt(b) - - is equivalent to: - - >>> c.decrypt(a+b) - - This function does not remove any padding from the plaintext. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if self.decrypt not in self._next: - raise TypeError("decrypt() cannot be called after encrypt()") - self._next = [ self.decrypt ] - - if output is None: - plaintext = create_string_buffer(len(ciphertext)) - else: - plaintext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(ciphertext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_cfb_lib.CFB_decrypt(self._state.get(), - c_uint8_ptr(ciphertext), - c_uint8_ptr(plaintext), - c_size_t(len(ciphertext))) - if result: - raise ValueError("Error %d while decrypting in CFB mode" % result) - - if output is None: - return get_raw_buffer(plaintext) - else: - return None - - -def _create_cfb_cipher(factory, **kwargs): - """Instantiate a cipher object that performs CFB encryption/decryption. - - :Parameters: - factory : module - The underlying block cipher, a module from ``Crypto.Cipher``. - - :Keywords: - iv : bytes/bytearray/memoryview - The IV to use for CFB. - - IV : bytes/bytearray/memoryview - Alias for ``iv``. - - segment_size : integer - The number of bit the plaintext and ciphertext are segmented in. - If not present, the default is 8. - - Any other keyword will be passed to the underlying block cipher. - See the relevant documentation for details (at least ``key`` will need - to be present). - """ - - cipher_state = factory._create_base_cipher(kwargs) - - iv = kwargs.pop("IV", None) - IV = kwargs.pop("iv", None) - - if (None, None) == (iv, IV): - iv = get_random_bytes(factory.block_size) - if iv is not None: - if IV is not None: - raise TypeError("You must either use 'iv' or 'IV', not both") - else: - iv = IV - - if len(iv) != factory.block_size: - raise ValueError("Incorrect IV length (it must be %d bytes long)" % - factory.block_size) - - segment_size_bytes, rem = divmod(kwargs.pop("segment_size", 8), 8) - if segment_size_bytes == 0 or rem != 0: - raise ValueError("'segment_size' must be positive and multiple of 8 bits") - - if kwargs: - raise TypeError("Unknown parameters for CFB: %s" % str(kwargs)) - return CfbMode(cipher_state, iv, segment_size_bytes) diff --git a/Crypto/Cipher/_mode_cfb.pyi b/Crypto/Cipher/_mode_cfb.pyi deleted file mode 100644 index e13a909..0000000 --- a/Crypto/Cipher/_mode_cfb.pyi +++ /dev/null @@ -1,26 +0,0 @@ -from typing import Union, overload - -from Crypto.Util._raw_api import SmartPointer - -Buffer = Union[bytes, bytearray, memoryview] - -__all__ = ['CfbMode'] - - -class CfbMode(object): - block_size: int - iv: Buffer - IV: Buffer - - def __init__(self, - block_cipher: SmartPointer, - iv: Buffer, - segment_size: int) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... diff --git a/Crypto/Cipher/_mode_ctr.py b/Crypto/Cipher/_mode_ctr.py deleted file mode 100644 index 15c7e83..0000000 --- a/Crypto/Cipher/_mode_ctr.py +++ /dev/null @@ -1,393 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Cipher/mode_ctr.py : CTR mode -# -# =================================================================== -# 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. -# =================================================================== - -""" -Counter (CTR) mode. -""" - -__all__ = ['CtrMode'] - -import struct - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - create_string_buffer, get_raw_buffer, - SmartPointer, c_size_t, c_uint8_ptr, - is_writeable_buffer) - -from Crypto.Random import get_random_bytes -from Crypto.Util.py3compat import _copy_bytes, is_native_int -from Crypto.Util.number import long_to_bytes - -raw_ctr_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_ctr", """ - int CTR_start_operation(void *cipher, - uint8_t initialCounterBlock[], - size_t initialCounterBlock_len, - size_t prefix_len, - unsigned counter_len, - unsigned littleEndian, - void **pResult); - int CTR_encrypt(void *ctrState, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int CTR_decrypt(void *ctrState, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int CTR_stop_operation(void *ctrState);""" - ) - - -class CtrMode(object): - """*CounTeR (CTR)* mode. - - This mode is very similar to ECB, in that - encryption of one block is done independently of all other blocks. - - Unlike ECB, the block *position* contributes to the encryption - and no information leaks about symbol frequency. - - Each message block is associated to a *counter* which - must be unique across all messages that get encrypted - with the same key (not just within the same message). - The counter is as big as the block size. - - Counters can be generated in several ways. The most - straightword one is to choose an *initial counter block* - (which can be made public, similarly to the *IV* for the - other modes) and increment its lowest **m** bits by one - (modulo *2^m*) for each block. In most cases, **m** is - chosen to be half the block size. - - See `NIST SP800-38A`_, Section 6.5 (for the mode) and - Appendix B (for how to manage the *initial counter block*). - - .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - - :undocumented: __init__ - """ - - def __init__(self, block_cipher, initial_counter_block, - prefix_len, counter_len, little_endian): - """Create a new block cipher, configured in CTR mode. - - :Parameters: - block_cipher : C pointer - A smart pointer to the low-level block cipher instance. - - initial_counter_block : bytes/bytearray/memoryview - The initial plaintext to use to generate the key stream. - - It is as large as the cipher block, and it embeds - the initial value of the counter. - - This value must not be reused. - It shall contain a nonce or a random component. - Reusing the *initial counter block* for encryptions - performed with the same key compromises confidentiality. - - prefix_len : integer - The amount of bytes at the beginning of the counter block - that never change. - - counter_len : integer - The length in bytes of the counter embedded in the counter - block. - - little_endian : boolean - True if the counter in the counter block is an integer encoded - in little endian mode. If False, it is big endian. - """ - - if len(initial_counter_block) == prefix_len + counter_len: - self.nonce = _copy_bytes(None, prefix_len, initial_counter_block) - """Nonce; not available if there is a fixed suffix""" - - self._state = VoidPointer() - result = raw_ctr_lib.CTR_start_operation(block_cipher.get(), - c_uint8_ptr(initial_counter_block), - c_size_t(len(initial_counter_block)), - c_size_t(prefix_len), - counter_len, - little_endian, - self._state.address_of()) - if result: - raise ValueError("Error %X while instantiating the CTR mode" - % result) - - # Ensure that object disposal of this Python object will (eventually) - # free the memory allocated by the raw library for the cipher mode - self._state = SmartPointer(self._state.get(), - raw_ctr_lib.CTR_stop_operation) - - # Memory allocated for the underlying block cipher is now owed - # by the cipher mode - block_cipher.release() - - self.block_size = len(initial_counter_block) - """The block size of the underlying cipher, in bytes.""" - - self._next = [self.encrypt, self.decrypt] - - def encrypt(self, plaintext, output=None): - """Encrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. - - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. - - That is, the statement: - - >>> c.encrypt(a) + c.encrypt(b) - - is equivalent to: - - >>> c.encrypt(a+b) - - This function does not add any padding to the plaintext. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if self.encrypt not in self._next: - raise TypeError("encrypt() cannot be called after decrypt()") - self._next = [self.encrypt] - - if output is None: - ciphertext = create_string_buffer(len(plaintext)) - else: - ciphertext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(plaintext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_ctr_lib.CTR_encrypt(self._state.get(), - c_uint8_ptr(plaintext), - c_uint8_ptr(ciphertext), - c_size_t(len(plaintext))) - if result: - if result == 0x60002: - raise OverflowError("The counter has wrapped around in" - " CTR mode") - raise ValueError("Error %X while encrypting in CTR mode" % result) - - if output is None: - return get_raw_buffer(ciphertext) - else: - return None - - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. - - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. - - That is, the statement: - - >>> c.decrypt(a) + c.decrypt(b) - - is equivalent to: - - >>> c.decrypt(a+b) - - This function does not remove any padding from the plaintext. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if self.decrypt not in self._next: - raise TypeError("decrypt() cannot be called after encrypt()") - self._next = [self.decrypt] - - if output is None: - plaintext = create_string_buffer(len(ciphertext)) - else: - plaintext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(ciphertext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_ctr_lib.CTR_decrypt(self._state.get(), - c_uint8_ptr(ciphertext), - c_uint8_ptr(plaintext), - c_size_t(len(ciphertext))) - if result: - if result == 0x60002: - raise OverflowError("The counter has wrapped around in" - " CTR mode") - raise ValueError("Error %X while decrypting in CTR mode" % result) - - if output is None: - return get_raw_buffer(plaintext) - else: - return None - - -def _create_ctr_cipher(factory, **kwargs): - """Instantiate a cipher object that performs CTR encryption/decryption. - - :Parameters: - factory : module - The underlying block cipher, a module from ``Crypto.Cipher``. - - :Keywords: - nonce : bytes/bytearray/memoryview - The fixed part at the beginning of the counter block - the rest is - the counter number that gets increased when processing the next block. - The nonce must be such that no two messages are encrypted under the - same key and the same nonce. - - The nonce must be shorter than the block size (it can have - zero length; the counter is then as long as the block). - - If this parameter is not present, a random nonce will be created with - length equal to half the block size. No random nonce shorter than - 64 bits will be created though - you must really think through all - security consequences of using such a short block size. - - initial_value : posive integer or bytes/bytearray/memoryview - The initial value for the counter. If not present, the cipher will - start counting from 0. The value is incremented by one for each block. - The counter number is encoded in big endian mode. - - counter : object - Instance of ``Crypto.Util.Counter``, which allows full customization - of the counter block. This parameter is incompatible to both ``nonce`` - and ``initial_value``. - - Any other keyword will be passed to the underlying block cipher. - See the relevant documentation for details (at least ``key`` will need - to be present). - """ - - cipher_state = factory._create_base_cipher(kwargs) - - counter = kwargs.pop("counter", None) - nonce = kwargs.pop("nonce", None) - initial_value = kwargs.pop("initial_value", None) - if kwargs: - raise TypeError("Invalid parameters for CTR mode: %s" % str(kwargs)) - - if counter is not None and (nonce, initial_value) != (None, None): - raise TypeError("'counter' and 'nonce'/'initial_value'" - " are mutually exclusive") - - if counter is None: - # Crypto.Util.Counter is not used - if nonce is None: - if factory.block_size < 16: - raise TypeError("Impossible to create a safe nonce for short" - " block sizes") - nonce = get_random_bytes(factory.block_size // 2) - else: - if len(nonce) >= factory.block_size: - raise ValueError("Nonce is too long") - - # What is not nonce is counter - counter_len = factory.block_size - len(nonce) - - if initial_value is None: - initial_value = 0 - - if is_native_int(initial_value): - if (1 << (counter_len * 8)) - 1 < initial_value: - raise ValueError("Initial counter value is too large") - initial_counter_block = nonce + long_to_bytes(initial_value, counter_len) - else: - if len(initial_value) != counter_len: - raise ValueError("Incorrect length for counter byte string (%d bytes, expected %d)" % - (len(initial_value), counter_len)) - initial_counter_block = nonce + initial_value - - return CtrMode(cipher_state, - initial_counter_block, - len(nonce), # prefix - counter_len, - False) # little_endian - - # Crypto.Util.Counter is used - - # 'counter' used to be a callable object, but now it is - # just a dictionary for backward compatibility. - _counter = dict(counter) - try: - counter_len = _counter.pop("counter_len") - prefix = _counter.pop("prefix") - suffix = _counter.pop("suffix") - initial_value = _counter.pop("initial_value") - little_endian = _counter.pop("little_endian") - except KeyError: - raise TypeError("Incorrect counter object" - " (use Crypto.Util.Counter.new)") - - # Compute initial counter block - words = [] - while initial_value > 0: - words.append(struct.pack('B', initial_value & 255)) - initial_value >>= 8 - words += [b'\x00'] * max(0, counter_len - len(words)) - if not little_endian: - words.reverse() - initial_counter_block = prefix + b"".join(words) + suffix - - if len(initial_counter_block) != factory.block_size: - raise ValueError("Size of the counter block (%d bytes) must match" - " block size (%d)" % (len(initial_counter_block), - factory.block_size)) - - return CtrMode(cipher_state, initial_counter_block, - len(prefix), counter_len, little_endian) diff --git a/Crypto/Cipher/_mode_ctr.pyi b/Crypto/Cipher/_mode_ctr.pyi deleted file mode 100644 index ce70855..0000000 --- a/Crypto/Cipher/_mode_ctr.pyi +++ /dev/null @@ -1,27 +0,0 @@ -from typing import Union, overload - -from Crypto.Util._raw_api import SmartPointer - -Buffer = Union[bytes, bytearray, memoryview] - -__all__ = ['CtrMode'] - -class CtrMode(object): - block_size: int - nonce: bytes - - def __init__(self, - block_cipher: SmartPointer, - initial_counter_block: Buffer, - prefix_len: int, - counter_len: int, - little_endian: bool) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - diff --git a/Crypto/Cipher/_mode_eax.py b/Crypto/Cipher/_mode_eax.py deleted file mode 100644 index d5fb135..0000000 --- a/Crypto/Cipher/_mode_eax.py +++ /dev/null @@ -1,408 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -""" -EAX mode. -""" - -__all__ = ['EaxMode'] - -import struct -from binascii import unhexlify - -from Crypto.Util.py3compat import byte_string, bord, _copy_bytes - -from Crypto.Util._raw_api import is_buffer - -from Crypto.Util.strxor import strxor -from Crypto.Util.number import long_to_bytes, bytes_to_long - -from Crypto.Hash import CMAC, BLAKE2s -from Crypto.Random import get_random_bytes - - -class EaxMode(object): - """*EAX* mode. - - This is an Authenticated Encryption with Associated Data - (`AEAD`_) mode. It provides both confidentiality and authenticity. - - The header of the message may be left in the clear, if needed, - and it will still be subject to authentication. - - The decryption step tells the receiver if the message comes - from a source that really knowns the secret key. - Additionally, decryption detects if any part of the message - - including the header - has been modified or corrupted. - - This mode requires a *nonce*. - - This mode is only available for ciphers that operate on 64 or - 128 bits blocks. - - There are no official standards defining EAX. - The implementation is based on `a proposal`__ that - was presented to NIST. - - .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html - .. __: http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/eax/eax-spec.pdf - - :undocumented: __init__ - """ - - def __init__(self, factory, key, nonce, mac_len, cipher_params): - """EAX cipher mode""" - - self.block_size = factory.block_size - """The block size of the underlying cipher, in bytes.""" - - self.nonce = _copy_bytes(None, None, nonce) - """The nonce originally used to create the object.""" - - self._mac_len = mac_len - self._mac_tag = None # Cache for MAC tag - - # Allowed transitions after initialization - self._next = [self.update, self.encrypt, self.decrypt, - self.digest, self.verify] - - # MAC tag length - if not (4 <= self._mac_len <= self.block_size): - raise ValueError("Parameter 'mac_len' must not be larger than %d" - % self.block_size) - - # Nonce cannot be empty and must be a byte string - if len(self.nonce) == 0: - raise ValueError("Nonce cannot be empty in EAX mode") - if not is_buffer(nonce): - raise TypeError("nonce must be bytes, bytearray or memoryview") - - self._omac = [ - CMAC.new(key, - b'\x00' * (self.block_size - 1) + struct.pack('B', i), - ciphermod=factory, - cipher_params=cipher_params) - for i in range(0, 3) - ] - - # Compute MAC of nonce - self._omac[0].update(self.nonce) - self._signer = self._omac[1] - - # MAC of the nonce is also the initial counter for CTR encryption - counter_int = bytes_to_long(self._omac[0].digest()) - self._cipher = factory.new(key, - factory.MODE_CTR, - initial_value=counter_int, - nonce=b"", - **cipher_params) - - def update(self, assoc_data): - """Protect associated data - - If there is any associated data, the caller has to invoke - this function one or more times, before using - ``decrypt`` or ``encrypt``. - - By *associated data* it is meant any data (e.g. packet headers) that - will not be encrypted and will be transmitted in the clear. - However, the receiver is still able to detect any modification to it. - - If there is no associated data, this method must not be called. - - The caller may split associated data in segments of any size, and - invoke this method multiple times, each time with the next segment. - - :Parameters: - assoc_data : bytes/bytearray/memoryview - A piece of associated data. There are no restrictions on its size. - """ - - if self.update not in self._next: - raise TypeError("update() can only be called" - " immediately after initialization") - - self._next = [self.update, self.encrypt, self.decrypt, - self.digest, self.verify] - - self._signer.update(assoc_data) - return self - - def encrypt(self, plaintext, output=None): - """Encrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. - - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. - - That is, the statement: - - >>> c.encrypt(a) + c.encrypt(b) - - is equivalent to: - - >>> c.encrypt(a+b) - - This function does not add any padding to the plaintext. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext as ``bytes``. - Otherwise, ``None``. - """ - - if self.encrypt not in self._next: - raise TypeError("encrypt() can only be called after" - " initialization or an update()") - self._next = [self.encrypt, self.digest] - ct = self._cipher.encrypt(plaintext, output=output) - if output is None: - self._omac[2].update(ct) - else: - self._omac[2].update(output) - return ct - - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. - - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. - - That is, the statement: - - >>> c.decrypt(a) + c.decrypt(b) - - is equivalent to: - - >>> c.decrypt(a+b) - - This function does not remove any padding from the plaintext. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext as ``bytes``. - Otherwise, ``None``. - """ - - if self.decrypt not in self._next: - raise TypeError("decrypt() can only be called" - " after initialization or an update()") - self._next = [self.decrypt, self.verify] - self._omac[2].update(ciphertext) - return self._cipher.decrypt(ciphertext, output=output) - - def digest(self): - """Compute the *binary* MAC tag. - - The caller invokes this function at the very end. - - This method returns the MAC that shall be sent to the receiver, - together with the ciphertext. - - :Return: the MAC, as a byte string. - """ - - if self.digest not in self._next: - raise TypeError("digest() cannot be called when decrypting" - " or validating a message") - self._next = [self.digest] - - if not self._mac_tag: - tag = b'\x00' * self.block_size - for i in range(3): - tag = strxor(tag, self._omac[i].digest()) - self._mac_tag = tag[:self._mac_len] - - return self._mac_tag - - def hexdigest(self): - """Compute the *printable* MAC tag. - - This method is like `digest`. - - :Return: the MAC, as a hexadecimal string. - """ - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def verify(self, received_mac_tag): - """Validate the *binary* MAC tag. - - The caller invokes this function at the very end. - - This method checks if the decrypted message is indeed valid - (that is, if the key is correct) and it has not been - tampered with while in transit. - - :Parameters: - received_mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Raises MacMismatchError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - if self.verify not in self._next: - raise TypeError("verify() cannot be called" - " when encrypting a message") - self._next = [self.verify] - - if not self._mac_tag: - tag = b'\x00' * self.block_size - for i in range(3): - tag = strxor(tag, self._omac[i].digest()) - self._mac_tag = tag[:self._mac_len] - - secret = get_random_bytes(16) - - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag) - - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") - - def hexverify(self, hex_mac_tag): - """Validate the *printable* MAC tag. - - This method is like `verify`. - - :Parameters: - hex_mac_tag : string - This is the *printable* MAC, as received from the sender. - :Raises MacMismatchError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - self.verify(unhexlify(hex_mac_tag)) - - def encrypt_and_digest(self, plaintext, output=None): - """Perform encrypt() and digest() in one step. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - a tuple with two items: - - - the ciphertext, as ``bytes`` - - the MAC tag, as ``bytes`` - - The first item becomes ``None`` when the ``output`` parameter - specified a location for the result. - """ - - return self.encrypt(plaintext, output=output), self.digest() - - def decrypt_and_verify(self, ciphertext, received_mac_tag, output=None): - """Perform decrypt() and verify() in one step. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - received_mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: the plaintext as ``bytes`` or ``None`` when the ``output`` - parameter specified a location for the result. - :Raises MacMismatchError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - pt = self.decrypt(ciphertext, output=output) - self.verify(received_mac_tag) - return pt - - -def _create_eax_cipher(factory, **kwargs): - """Create a new block cipher, configured in EAX mode. - - :Parameters: - factory : module - A symmetric cipher module from `Crypto.Cipher` (like - `Crypto.Cipher.AES`). - - :Keywords: - key : bytes/bytearray/memoryview - The secret key to use in the symmetric cipher. - - nonce : bytes/bytearray/memoryview - A value that must never be reused for any other encryption. - There are no restrictions on its length, but it is recommended to use - at least 16 bytes. - - The nonce shall never repeat for two different messages encrypted with - the same key, but it does not need to be random. - - If not specified, a 16 byte long random string is used. - - mac_len : integer - Length of the MAC, in bytes. It must be no larger than the cipher - block bytes (which is the default). - """ - - try: - key = kwargs.pop("key") - nonce = kwargs.pop("nonce", None) - if nonce is None: - nonce = get_random_bytes(16) - mac_len = kwargs.pop("mac_len", factory.block_size) - except KeyError as e: - raise TypeError("Missing parameter: " + str(e)) - - return EaxMode(factory, key, nonce, mac_len, kwargs) diff --git a/Crypto/Cipher/_mode_eax.pyi b/Crypto/Cipher/_mode_eax.pyi deleted file mode 100644 index cbfa467..0000000 --- a/Crypto/Cipher/_mode_eax.pyi +++ /dev/null @@ -1,45 +0,0 @@ -from types import ModuleType -from typing import Any, Union, Tuple, Dict, overload, Optional - -Buffer = Union[bytes, bytearray, memoryview] - -__all__ = ['EaxMode'] - -class EaxMode(object): - block_size: int - nonce: bytes - - def __init__(self, - factory: ModuleType, - key: Buffer, - nonce: Buffer, - mac_len: int, - cipher_params: Dict) -> None: ... - - def update(self, assoc_data: Buffer) -> EaxMode: ... - - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, received_mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - - @overload - def encrypt_and_digest(self, - plaintext: Buffer) -> Tuple[bytes, bytes]: ... - @overload - def encrypt_and_digest(self, - plaintext: Buffer, - output: Buffer) -> Tuple[None, bytes]: ... - def decrypt_and_verify(self, - ciphertext: Buffer, - received_mac_tag: Buffer, - output: Optional[Union[bytearray, memoryview]] = ...) -> bytes: ... diff --git a/Crypto/Cipher/_mode_ecb.py b/Crypto/Cipher/_mode_ecb.py deleted file mode 100644 index 3783357..0000000 --- a/Crypto/Cipher/_mode_ecb.py +++ /dev/null @@ -1,220 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Cipher/mode_ecb.py : ECB mode -# -# =================================================================== -# 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. -# =================================================================== - -""" -Electronic Code Book (ECB) mode. -""" - -__all__ = [ 'EcbMode' ] - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, create_string_buffer, - get_raw_buffer, SmartPointer, - c_size_t, c_uint8_ptr, - is_writeable_buffer) - -raw_ecb_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_ecb", """ - int ECB_start_operation(void *cipher, - void **pResult); - int ECB_encrypt(void *ecbState, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int ECB_decrypt(void *ecbState, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int ECB_stop_operation(void *state); - """ - ) - - -class EcbMode(object): - """*Electronic Code Book (ECB)*. - - This is the simplest encryption mode. Each of the plaintext blocks - is directly encrypted into a ciphertext block, independently of - any other block. - - This mode is dangerous because it exposes frequency of symbols - in your plaintext. Other modes (e.g. *CBC*) should be used instead. - - See `NIST SP800-38A`_ , Section 6.1. - - .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - - :undocumented: __init__ - """ - - def __init__(self, block_cipher): - """Create a new block cipher, configured in ECB mode. - - :Parameters: - block_cipher : C pointer - A smart pointer to the low-level block cipher instance. - """ - self.block_size = block_cipher.block_size - - self._state = VoidPointer() - result = raw_ecb_lib.ECB_start_operation(block_cipher.get(), - self._state.address_of()) - if result: - raise ValueError("Error %d while instantiating the ECB mode" - % result) - - # Ensure that object disposal of this Python object will (eventually) - # free the memory allocated by the raw library for the cipher - # mode - self._state = SmartPointer(self._state.get(), - raw_ecb_lib.ECB_stop_operation) - - # Memory allocated for the underlying block cipher is now owned - # by the cipher mode - block_cipher.release() - - def encrypt(self, plaintext, output=None): - """Encrypt data with the key set at initialization. - - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. - - That is, the statement: - - >>> c.encrypt(a) + c.encrypt(b) - - is equivalent to: - - >>> c.encrypt(a+b) - - This function does not add any padding to the plaintext. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - The length must be multiple of the cipher block length. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if output is None: - ciphertext = create_string_buffer(len(plaintext)) - else: - ciphertext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(plaintext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_ecb_lib.ECB_encrypt(self._state.get(), - c_uint8_ptr(plaintext), - c_uint8_ptr(ciphertext), - c_size_t(len(plaintext))) - if result: - if result == 3: - raise ValueError("Data must be aligned to block boundary in ECB mode") - raise ValueError("Error %d while encrypting in ECB mode" % result) - - if output is None: - return get_raw_buffer(ciphertext) - else: - return None - - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key set at initialization. - - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. - - That is, the statement: - - >>> c.decrypt(a) + c.decrypt(b) - - is equivalent to: - - >>> c.decrypt(a+b) - - This function does not remove any padding from the plaintext. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - The length must be multiple of the cipher block length. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if output is None: - plaintext = create_string_buffer(len(ciphertext)) - else: - plaintext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(ciphertext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_ecb_lib.ECB_decrypt(self._state.get(), - c_uint8_ptr(ciphertext), - c_uint8_ptr(plaintext), - c_size_t(len(ciphertext))) - if result: - if result == 3: - raise ValueError("Data must be aligned to block boundary in ECB mode") - raise ValueError("Error %d while decrypting in ECB mode" % result) - - if output is None: - return get_raw_buffer(plaintext) - else: - return None - - -def _create_ecb_cipher(factory, **kwargs): - """Instantiate a cipher object that performs ECB encryption/decryption. - - :Parameters: - factory : module - The underlying block cipher, a module from ``Crypto.Cipher``. - - All keywords are passed to the underlying block cipher. - See the relevant documentation for details (at least ``key`` will need - to be present""" - - cipher_state = factory._create_base_cipher(kwargs) - cipher_state.block_size = factory.block_size - if kwargs: - raise TypeError("Unknown parameters for ECB: %s" % str(kwargs)) - return EcbMode(cipher_state) diff --git a/Crypto/Cipher/_mode_ecb.pyi b/Crypto/Cipher/_mode_ecb.pyi deleted file mode 100644 index 1772b23..0000000 --- a/Crypto/Cipher/_mode_ecb.pyi +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Union, overload - -from Crypto.Util._raw_api import SmartPointer - -Buffer = Union[bytes, bytearray, memoryview] - -__all__ = [ 'EcbMode' ] - -class EcbMode(object): - def __init__(self, block_cipher: SmartPointer) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - diff --git a/Crypto/Cipher/_mode_gcm.py b/Crypto/Cipher/_mode_gcm.py deleted file mode 100644 index da8e337..0000000 --- a/Crypto/Cipher/_mode_gcm.py +++ /dev/null @@ -1,620 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -""" -Galois/Counter Mode (GCM). -""" - -__all__ = ['GcmMode'] - -from binascii import unhexlify - -from Crypto.Util.py3compat import bord, _copy_bytes - -from Crypto.Util._raw_api import is_buffer - -from Crypto.Util.number import long_to_bytes, bytes_to_long -from Crypto.Hash import BLAKE2s -from Crypto.Random import get_random_bytes - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - create_string_buffer, get_raw_buffer, - SmartPointer, c_size_t, c_uint8_ptr) - -from Crypto.Util import _cpu_features - - -# C API by module implementing GHASH -_ghash_api_template = """ - int ghash_%imp%(uint8_t y_out[16], - const uint8_t block_data[], - size_t len, - const uint8_t y_in[16], - const void *exp_key); - int ghash_expand_%imp%(const uint8_t h[16], - void **ghash_tables); - int ghash_destroy_%imp%(void *ghash_tables); -""" - -def _build_impl(lib, postfix): - from collections import namedtuple - - funcs = ( "ghash", "ghash_expand", "ghash_destroy" ) - GHASH_Imp = namedtuple('_GHash_Imp', funcs) - try: - imp_funcs = [ getattr(lib, x + "_" + postfix) for x in funcs ] - except AttributeError: # Make sphinx stop complaining with its mocklib - imp_funcs = [ None ] * 3 - params = dict(zip(funcs, imp_funcs)) - return GHASH_Imp(**params) - - -def _get_ghash_portable(): - api = _ghash_api_template.replace("%imp%", "portable") - lib = load_pycryptodome_raw_lib("Crypto.Hash._ghash_portable", api) - result = _build_impl(lib, "portable") - return result -_ghash_portable = _get_ghash_portable() - - -def _get_ghash_clmul(): - """Return None if CLMUL implementation is not available""" - - if not _cpu_features.have_clmul(): - return None - try: - api = _ghash_api_template.replace("%imp%", "clmul") - lib = load_pycryptodome_raw_lib("Crypto.Hash._ghash_clmul", api) - result = _build_impl(lib, "clmul") - except OSError: - result = None - return result -_ghash_clmul = _get_ghash_clmul() - - -class _GHASH(object): - """GHASH function defined in NIST SP 800-38D, Algorithm 2. - - If X_1, X_2, .. X_m are the blocks of input data, the function - computes: - - X_1*H^{m} + X_2*H^{m-1} + ... + X_m*H - - in the Galois field GF(2^256) using the reducing polynomial - (x^128 + x^7 + x^2 + x + 1). - """ - - def __init__(self, subkey, ghash_c): - assert len(subkey) == 16 - - self.ghash_c = ghash_c - - self._exp_key = VoidPointer() - result = ghash_c.ghash_expand(c_uint8_ptr(subkey), - self._exp_key.address_of()) - if result: - raise ValueError("Error %d while expanding the GHASH key" % result) - - self._exp_key = SmartPointer(self._exp_key.get(), - ghash_c.ghash_destroy) - - # create_string_buffer always returns a string of zeroes - self._last_y = create_string_buffer(16) - - def update(self, block_data): - assert len(block_data) % 16 == 0 - - result = self.ghash_c.ghash(self._last_y, - c_uint8_ptr(block_data), - c_size_t(len(block_data)), - self._last_y, - self._exp_key.get()) - if result: - raise ValueError("Error %d while updating GHASH" % result) - - return self - - def digest(self): - return get_raw_buffer(self._last_y) - - -def enum(**enums): - return type('Enum', (), enums) - - -MacStatus = enum(PROCESSING_AUTH_DATA=1, PROCESSING_CIPHERTEXT=2) - - -class GcmMode(object): - """Galois Counter Mode (GCM). - - This is an Authenticated Encryption with Associated Data (`AEAD`_) mode. - It provides both confidentiality and authenticity. - - The header of the message may be left in the clear, if needed, and it will - still be subject to authentication. The decryption step tells the receiver - if the message comes from a source that really knowns the secret key. - Additionally, decryption detects if any part of the message - including the - header - has been modified or corrupted. - - This mode requires a *nonce*. - - This mode is only available for ciphers that operate on 128 bits blocks - (e.g. AES but not TDES). - - See `NIST SP800-38D`_. - - .. _`NIST SP800-38D`: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf - .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html - - :undocumented: __init__ - """ - - def __init__(self, factory, key, nonce, mac_len, cipher_params, ghash_c): - - self.block_size = factory.block_size - if self.block_size != 16: - raise ValueError("GCM mode is only available for ciphers" - " that operate on 128 bits blocks") - - if len(nonce) == 0: - raise ValueError("Nonce cannot be empty") - - if not is_buffer(nonce): - raise TypeError("Nonce must be bytes, bytearray or memoryview") - - # See NIST SP 800 38D, 5.2.1.1 - if len(nonce) > 2**64 - 1: - raise ValueError("Nonce exceeds maximum length") - - - self.nonce = _copy_bytes(None, None, nonce) - """Nonce""" - - self._factory = factory - self._key = _copy_bytes(None, None, key) - self._tag = None # Cache for MAC tag - - self._mac_len = mac_len - if not (4 <= mac_len <= 16): - raise ValueError("Parameter 'mac_len' must be in the range 4..16") - - # Allowed transitions after initialization - self._next = [self.update, self.encrypt, self.decrypt, - self.digest, self.verify] - - self._no_more_assoc_data = False - - # Length of associated data - self._auth_len = 0 - - # Length of the ciphertext or plaintext - self._msg_len = 0 - - # Step 1 in SP800-38D, Algorithm 4 (encryption) - Compute H - # See also Algorithm 5 (decryption) - hash_subkey = factory.new(key, - self._factory.MODE_ECB, - **cipher_params - ).encrypt(b'\x00' * 16) - - # Step 2 - Compute J0 - if len(self.nonce) == 12: - j0 = self.nonce + b"\x00\x00\x00\x01" - else: - fill = (16 - (len(nonce) % 16)) % 16 + 8 - ghash_in = (self.nonce + - b'\x00' * fill + - long_to_bytes(8 * len(nonce), 8)) - j0 = _GHASH(hash_subkey, ghash_c).update(ghash_in).digest() - - # Step 3 - Prepare GCTR cipher for encryption/decryption - nonce_ctr = j0[:12] - iv_ctr = (bytes_to_long(j0) + 1) & 0xFFFFFFFF - self._cipher = factory.new(key, - self._factory.MODE_CTR, - initial_value=iv_ctr, - nonce=nonce_ctr, - **cipher_params) - - # Step 5 - Bootstrat GHASH - self._signer = _GHASH(hash_subkey, ghash_c) - - # Step 6 - Prepare GCTR cipher for GMAC - self._tag_cipher = factory.new(key, - self._factory.MODE_CTR, - initial_value=j0, - nonce=b"", - **cipher_params) - - # Cache for data to authenticate - self._cache = b"" - - self._status = MacStatus.PROCESSING_AUTH_DATA - - def update(self, assoc_data): - """Protect associated data - - If there is any associated data, the caller has to invoke - this function one or more times, before using - ``decrypt`` or ``encrypt``. - - By *associated data* it is meant any data (e.g. packet headers) that - will not be encrypted and will be transmitted in the clear. - However, the receiver is still able to detect any modification to it. - In GCM, the *associated data* is also called - *additional authenticated data* (AAD). - - If there is no associated data, this method must not be called. - - The caller may split associated data in segments of any size, and - invoke this method multiple times, each time with the next segment. - - :Parameters: - assoc_data : bytes/bytearray/memoryview - A piece of associated data. There are no restrictions on its size. - """ - - if self.update not in self._next: - raise TypeError("update() can only be called" - " immediately after initialization") - - self._next = [self.update, self.encrypt, self.decrypt, - self.digest, self.verify] - - self._update(assoc_data) - self._auth_len += len(assoc_data) - - # See NIST SP 800 38D, 5.2.1.1 - if self._auth_len > 2**64 - 1: - raise ValueError("Additional Authenticated Data exceeds maximum length") - - return self - - def _update(self, data): - assert(len(self._cache) < 16) - - if len(self._cache) > 0: - filler = min(16 - len(self._cache), len(data)) - self._cache += _copy_bytes(None, filler, data) - data = data[filler:] - - if len(self._cache) < 16: - return - - # The cache is exactly one block - self._signer.update(self._cache) - self._cache = b"" - - update_len = len(data) // 16 * 16 - self._cache = _copy_bytes(update_len, None, data) - if update_len > 0: - self._signer.update(data[:update_len]) - - def _pad_cache_and_update(self): - assert(len(self._cache) < 16) - - # The authenticated data A is concatenated to the minimum - # number of zero bytes (possibly none) such that the - # - ciphertext C is aligned to the 16 byte boundary. - # See step 5 in section 7.1 - # - ciphertext C is aligned to the 16 byte boundary. - # See step 6 in section 7.2 - len_cache = len(self._cache) - if len_cache > 0: - self._update(b'\x00' * (16 - len_cache)) - - def encrypt(self, plaintext, output=None): - """Encrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. - - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. - - That is, the statement: - - >>> c.encrypt(a) + c.encrypt(b) - - is equivalent to: - - >>> c.encrypt(a+b) - - This function does not add any padding to the plaintext. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext as ``bytes``. - Otherwise, ``None``. - """ - - if self.encrypt not in self._next: - raise TypeError("encrypt() can only be called after" - " initialization or an update()") - self._next = [self.encrypt, self.digest] - - ciphertext = self._cipher.encrypt(plaintext, output=output) - - if self._status == MacStatus.PROCESSING_AUTH_DATA: - self._pad_cache_and_update() - self._status = MacStatus.PROCESSING_CIPHERTEXT - - self._update(ciphertext if output is None else output) - self._msg_len += len(plaintext) - - # See NIST SP 800 38D, 5.2.1.1 - if self._msg_len > 2**39 - 256: - raise ValueError("Plaintext exceeds maximum length") - - return ciphertext - - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. - - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. - - That is, the statement: - - >>> c.decrypt(a) + c.decrypt(b) - - is equivalent to: - - >>> c.decrypt(a+b) - - This function does not remove any padding from the plaintext. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext as ``bytes``. - Otherwise, ``None``. - """ - - if self.decrypt not in self._next: - raise TypeError("decrypt() can only be called" - " after initialization or an update()") - self._next = [self.decrypt, self.verify] - - if self._status == MacStatus.PROCESSING_AUTH_DATA: - self._pad_cache_and_update() - self._status = MacStatus.PROCESSING_CIPHERTEXT - - self._update(ciphertext) - self._msg_len += len(ciphertext) - - return self._cipher.decrypt(ciphertext, output=output) - - def digest(self): - """Compute the *binary* MAC tag in an AEAD mode. - - The caller invokes this function at the very end. - - This method returns the MAC that shall be sent to the receiver, - together with the ciphertext. - - :Return: the MAC, as a byte string. - """ - - if self.digest not in self._next: - raise TypeError("digest() cannot be called when decrypting" - " or validating a message") - self._next = [self.digest] - - return self._compute_mac() - - def _compute_mac(self): - """Compute MAC without any FSM checks.""" - - if self._tag: - return self._tag - - # Step 5 in NIST SP 800-38D, Algorithm 4 - Compute S - self._pad_cache_and_update() - self._update(long_to_bytes(8 * self._auth_len, 8)) - self._update(long_to_bytes(8 * self._msg_len, 8)) - s_tag = self._signer.digest() - - # Step 6 - Compute T - self._tag = self._tag_cipher.encrypt(s_tag)[:self._mac_len] - - return self._tag - - def hexdigest(self): - """Compute the *printable* MAC tag. - - This method is like `digest`. - - :Return: the MAC, as a hexadecimal string. - """ - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def verify(self, received_mac_tag): - """Validate the *binary* MAC tag. - - The caller invokes this function at the very end. - - This method checks if the decrypted message is indeed valid - (that is, if the key is correct) and it has not been - tampered with while in transit. - - :Parameters: - received_mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - if self.verify not in self._next: - raise TypeError("verify() cannot be called" - " when encrypting a message") - self._next = [self.verify] - - secret = get_random_bytes(16) - - mac1 = BLAKE2s.new(digest_bits=160, key=secret, - data=self._compute_mac()) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, - data=received_mac_tag) - - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") - - def hexverify(self, hex_mac_tag): - """Validate the *printable* MAC tag. - - This method is like `verify`. - - :Parameters: - hex_mac_tag : string - This is the *printable* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - self.verify(unhexlify(hex_mac_tag)) - - def encrypt_and_digest(self, plaintext, output=None): - """Perform encrypt() and digest() in one step. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - a tuple with two items: - - - the ciphertext, as ``bytes`` - - the MAC tag, as ``bytes`` - - The first item becomes ``None`` when the ``output`` parameter - specified a location for the result. - """ - - return self.encrypt(plaintext, output=output), self.digest() - - def decrypt_and_verify(self, ciphertext, received_mac_tag, output=None): - """Perform decrypt() and verify() in one step. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - received_mac_tag : byte string - This is the *binary* MAC, as received from the sender. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: the plaintext as ``bytes`` or ``None`` when the ``output`` - parameter specified a location for the result. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - plaintext = self.decrypt(ciphertext, output=output) - self.verify(received_mac_tag) - return plaintext - - -def _create_gcm_cipher(factory, **kwargs): - """Create a new block cipher, configured in Galois Counter Mode (GCM). - - :Parameters: - factory : module - A block cipher module, taken from `Crypto.Cipher`. - The cipher must have block length of 16 bytes. - GCM has been only defined for `Crypto.Cipher.AES`. - - :Keywords: - key : bytes/bytearray/memoryview - The secret key to use in the symmetric cipher. - It must be 16 (e.g. *AES-128*), 24 (e.g. *AES-192*) - or 32 (e.g. *AES-256*) bytes long. - - nonce : bytes/bytearray/memoryview - A value that must never be reused for any other encryption. - - There are no restrictions on its length, - but it is recommended to use at least 16 bytes. - - The nonce shall never repeat for two - different messages encrypted with the same key, - but it does not need to be random. - - If not provided, a 16 byte nonce will be randomly created. - - mac_len : integer - Length of the MAC, in bytes. - It must be no larger than 16 bytes (which is the default). - """ - - try: - key = kwargs.pop("key") - except KeyError as e: - raise TypeError("Missing parameter:" + str(e)) - - nonce = kwargs.pop("nonce", None) - if nonce is None: - nonce = get_random_bytes(16) - mac_len = kwargs.pop("mac_len", 16) - - # Not documented - only used for testing - use_clmul = kwargs.pop("use_clmul", True) - if use_clmul and _ghash_clmul: - ghash_c = _ghash_clmul - else: - ghash_c = _ghash_portable - - return GcmMode(factory, key, nonce, mac_len, kwargs, ghash_c) diff --git a/Crypto/Cipher/_mode_gcm.pyi b/Crypto/Cipher/_mode_gcm.pyi deleted file mode 100644 index 8912955..0000000 --- a/Crypto/Cipher/_mode_gcm.pyi +++ /dev/null @@ -1,45 +0,0 @@ -from types import ModuleType -from typing import Union, Tuple, Dict, overload, Optional - -__all__ = ['GcmMode'] - -Buffer = Union[bytes, bytearray, memoryview] - -class GcmMode(object): - block_size: int - nonce: Buffer - - def __init__(self, - factory: ModuleType, - key: Buffer, - nonce: Buffer, - mac_len: int, - cipher_params: Dict) -> None: ... - - def update(self, assoc_data: Buffer) -> GcmMode: ... - - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, received_mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - - @overload - def encrypt_and_digest(self, - plaintext: Buffer) -> Tuple[bytes, bytes]: ... - @overload - def encrypt_and_digest(self, - plaintext: Buffer, - output: Buffer) -> Tuple[None, bytes]: ... - def decrypt_and_verify(self, - ciphertext: Buffer, - received_mac_tag: Buffer, - output: Optional[Union[bytearray, memoryview]] = ...) -> bytes: ... diff --git a/Crypto/Cipher/_mode_ocb.py b/Crypto/Cipher/_mode_ocb.py deleted file mode 100644 index 27758b1..0000000 --- a/Crypto/Cipher/_mode_ocb.py +++ /dev/null @@ -1,525 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -""" -Offset Codebook (OCB) mode. - -OCB is Authenticated Encryption with Associated Data (AEAD) cipher mode -designed by Prof. Phillip Rogaway and specified in `RFC7253`_. - -The algorithm provides both authenticity and privacy, it is very efficient, -it uses only one key and it can be used in online mode (so that encryption -or decryption can start before the end of the message is available). - -This module implements the third and last variant of OCB (OCB3) and it only -works in combination with a 128-bit block symmetric cipher, like AES. - -OCB is patented in US but `free licenses`_ exist for software implementations -meant for non-military purposes. - -Example: - >>> from Crypto.Cipher import AES - >>> from Crypto.Random import get_random_bytes - >>> - >>> key = get_random_bytes(32) - >>> cipher = AES.new(key, AES.MODE_OCB) - >>> plaintext = b"Attack at dawn" - >>> ciphertext, mac = cipher.encrypt_and_digest(plaintext) - >>> # Deliver cipher.nonce, ciphertext and mac - ... - >>> cipher = AES.new(key, AES.MODE_OCB, nonce=nonce) - >>> try: - >>> plaintext = cipher.decrypt_and_verify(ciphertext, mac) - >>> except ValueError: - >>> print "Invalid message" - >>> else: - >>> print plaintext - -:undocumented: __package__ - -.. _RFC7253: http://www.rfc-editor.org/info/rfc7253 -.. _free licenses: http://web.cs.ucdavis.edu/~rogaway/ocb/license.htm -""" - -import struct -from binascii import unhexlify - -from Crypto.Util.py3compat import bord, _copy_bytes -from Crypto.Util.number import long_to_bytes, bytes_to_long -from Crypto.Util.strxor import strxor - -from Crypto.Hash import BLAKE2s -from Crypto.Random import get_random_bytes - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - create_string_buffer, get_raw_buffer, - SmartPointer, c_size_t, c_uint8_ptr, - is_buffer) - -_raw_ocb_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_ocb", """ - int OCB_start_operation(void *cipher, - const uint8_t *offset_0, - size_t offset_0_len, - void **pState); - int OCB_encrypt(void *state, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int OCB_decrypt(void *state, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int OCB_update(void *state, - const uint8_t *in, - size_t data_len); - int OCB_digest(void *state, - uint8_t *tag, - size_t tag_len); - int OCB_stop_operation(void *state); - """) - - -class OcbMode(object): - """Offset Codebook (OCB) mode. - - :undocumented: __init__ - """ - - def __init__(self, factory, nonce, mac_len, cipher_params): - - if factory.block_size != 16: - raise ValueError("OCB mode is only available for ciphers" - " that operate on 128 bits blocks") - - self.block_size = 16 - """The block size of the underlying cipher, in bytes.""" - - self.nonce = _copy_bytes(None, None, nonce) - """Nonce used for this session.""" - if len(nonce) not in range(1, 16): - raise ValueError("Nonce must be at most 15 bytes long") - if not is_buffer(nonce): - raise TypeError("Nonce must be bytes, bytearray or memoryview") - - self._mac_len = mac_len - if not 8 <= mac_len <= 16: - raise ValueError("MAC tag must be between 8 and 16 bytes long") - - # Cache for MAC tag - self._mac_tag = None - - # Cache for unaligned associated data - self._cache_A = b"" - - # Cache for unaligned ciphertext/plaintext - self._cache_P = b"" - - # Allowed transitions after initialization - self._next = [self.update, self.encrypt, self.decrypt, - self.digest, self.verify] - - # Compute Offset_0 - params_without_key = dict(cipher_params) - key = params_without_key.pop("key") - nonce = (struct.pack('B', self._mac_len << 4 & 0xFF) + - b'\x00' * (14 - len(nonce)) + - b'\x01' + self.nonce) - - bottom_bits = bord(nonce[15]) & 0x3F # 6 bits, 0..63 - top_bits = bord(nonce[15]) & 0xC0 # 2 bits - - ktop_cipher = factory.new(key, - factory.MODE_ECB, - **params_without_key) - ktop = ktop_cipher.encrypt(struct.pack('15sB', - nonce[:15], - top_bits)) - - stretch = ktop + strxor(ktop[:8], ktop[1:9]) # 192 bits - offset_0 = long_to_bytes(bytes_to_long(stretch) >> - (64 - bottom_bits), 24)[8:] - - # Create low-level cipher instance - raw_cipher = factory._create_base_cipher(cipher_params) - if cipher_params: - raise TypeError("Unknown keywords: " + str(cipher_params)) - - self._state = VoidPointer() - result = _raw_ocb_lib.OCB_start_operation(raw_cipher.get(), - offset_0, - c_size_t(len(offset_0)), - self._state.address_of()) - if result: - raise ValueError("Error %d while instantiating the OCB mode" - % result) - - # Ensure that object disposal of this Python object will (eventually) - # free the memory allocated by the raw library for the cipher mode - self._state = SmartPointer(self._state.get(), - _raw_ocb_lib.OCB_stop_operation) - - # Memory allocated for the underlying block cipher is now owed - # by the cipher mode - raw_cipher.release() - - def _update(self, assoc_data, assoc_data_len): - result = _raw_ocb_lib.OCB_update(self._state.get(), - c_uint8_ptr(assoc_data), - c_size_t(assoc_data_len)) - if result: - raise ValueError("Error %d while computing MAC in OCB mode" % result) - - def update(self, assoc_data): - """Process the associated data. - - If there is any associated data, the caller has to invoke - this method one or more times, before using - ``decrypt`` or ``encrypt``. - - By *associated data* it is meant any data (e.g. packet headers) that - will not be encrypted and will be transmitted in the clear. - However, the receiver shall still able to detect modifications. - - If there is no associated data, this method must not be called. - - The caller may split associated data in segments of any size, and - invoke this method multiple times, each time with the next segment. - - :Parameters: - assoc_data : bytes/bytearray/memoryview - A piece of associated data. - """ - - if self.update not in self._next: - raise TypeError("update() can only be called" - " immediately after initialization") - - self._next = [self.encrypt, self.decrypt, self.digest, - self.verify, self.update] - - if len(self._cache_A) > 0: - filler = min(16 - len(self._cache_A), len(assoc_data)) - self._cache_A += _copy_bytes(None, filler, assoc_data) - assoc_data = assoc_data[filler:] - - if len(self._cache_A) < 16: - return self - - # Clear the cache, and proceeding with any other aligned data - self._cache_A, seg = b"", self._cache_A - self.update(seg) - - update_len = len(assoc_data) // 16 * 16 - self._cache_A = _copy_bytes(update_len, None, assoc_data) - self._update(assoc_data, update_len) - return self - - def _transcrypt_aligned(self, in_data, in_data_len, - trans_func, trans_desc): - - out_data = create_string_buffer(in_data_len) - result = trans_func(self._state.get(), - in_data, - out_data, - c_size_t(in_data_len)) - if result: - raise ValueError("Error %d while %sing in OCB mode" - % (result, trans_desc)) - return get_raw_buffer(out_data) - - def _transcrypt(self, in_data, trans_func, trans_desc): - # Last piece to encrypt/decrypt - if in_data is None: - out_data = self._transcrypt_aligned(self._cache_P, - len(self._cache_P), - trans_func, - trans_desc) - self._cache_P = b"" - return out_data - - # Try to fill up the cache, if it already contains something - prefix = b"" - if len(self._cache_P) > 0: - filler = min(16 - len(self._cache_P), len(in_data)) - self._cache_P += _copy_bytes(None, filler, in_data) - in_data = in_data[filler:] - - if len(self._cache_P) < 16: - # We could not manage to fill the cache, so there is certainly - # no output yet. - return b"" - - # Clear the cache, and proceeding with any other aligned data - prefix = self._transcrypt_aligned(self._cache_P, - len(self._cache_P), - trans_func, - trans_desc) - self._cache_P = b"" - - # Process data in multiples of the block size - trans_len = len(in_data) // 16 * 16 - result = self._transcrypt_aligned(c_uint8_ptr(in_data), - trans_len, - trans_func, - trans_desc) - if prefix: - result = prefix + result - - # Left-over - self._cache_P = _copy_bytes(trans_len, None, in_data) - - return result - - def encrypt(self, plaintext=None): - """Encrypt the next piece of plaintext. - - After the entire plaintext has been passed (but before `digest`), - you **must** call this method one last time with no arguments to collect - the final piece of ciphertext. - - If possible, use the method `encrypt_and_digest` instead. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The next piece of data to encrypt or ``None`` to signify - that encryption has finished and that any remaining ciphertext - has to be produced. - :Return: - the ciphertext, as a byte string. - Its length may not match the length of the *plaintext*. - """ - - if self.encrypt not in self._next: - raise TypeError("encrypt() can only be called after" - " initialization or an update()") - - if plaintext is None: - self._next = [self.digest] - else: - self._next = [self.encrypt] - return self._transcrypt(plaintext, _raw_ocb_lib.OCB_encrypt, "encrypt") - - def decrypt(self, ciphertext=None): - """Decrypt the next piece of ciphertext. - - After the entire ciphertext has been passed (but before `verify`), - you **must** call this method one last time with no arguments to collect - the remaining piece of plaintext. - - If possible, use the method `decrypt_and_verify` instead. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The next piece of data to decrypt or ``None`` to signify - that decryption has finished and that any remaining plaintext - has to be produced. - :Return: - the plaintext, as a byte string. - Its length may not match the length of the *ciphertext*. - """ - - if self.decrypt not in self._next: - raise TypeError("decrypt() can only be called after" - " initialization or an update()") - - if ciphertext is None: - self._next = [self.verify] - else: - self._next = [self.decrypt] - return self._transcrypt(ciphertext, - _raw_ocb_lib.OCB_decrypt, - "decrypt") - - def _compute_mac_tag(self): - - if self._mac_tag is not None: - return - - if self._cache_A: - self._update(self._cache_A, len(self._cache_A)) - self._cache_A = b"" - - mac_tag = create_string_buffer(16) - result = _raw_ocb_lib.OCB_digest(self._state.get(), - mac_tag, - c_size_t(len(mac_tag)) - ) - if result: - raise ValueError("Error %d while computing digest in OCB mode" - % result) - self._mac_tag = get_raw_buffer(mac_tag)[:self._mac_len] - - def digest(self): - """Compute the *binary* MAC tag. - - Call this method after the final `encrypt` (the one with no arguments) - to obtain the MAC tag. - - The MAC tag is needed by the receiver to determine authenticity - of the message. - - :Return: the MAC, as a byte string. - """ - - if self.digest not in self._next: - raise TypeError("digest() cannot be called now for this cipher") - - assert(len(self._cache_P) == 0) - - self._next = [self.digest] - - if self._mac_tag is None: - self._compute_mac_tag() - - return self._mac_tag - - def hexdigest(self): - """Compute the *printable* MAC tag. - - This method is like `digest`. - - :Return: the MAC, as a hexadecimal string. - """ - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def verify(self, received_mac_tag): - """Validate the *binary* MAC tag. - - Call this method after the final `decrypt` (the one with no arguments) - to check if the message is authentic and valid. - - :Parameters: - received_mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - if self.verify not in self._next: - raise TypeError("verify() cannot be called now for this cipher") - - assert(len(self._cache_P) == 0) - - self._next = [self.verify] - - if self._mac_tag is None: - self._compute_mac_tag() - - secret = get_random_bytes(16) - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag) - - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") - - def hexverify(self, hex_mac_tag): - """Validate the *printable* MAC tag. - - This method is like `verify`. - - :Parameters: - hex_mac_tag : string - This is the *printable* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - self.verify(unhexlify(hex_mac_tag)) - - def encrypt_and_digest(self, plaintext): - """Encrypt the message and create the MAC tag in one step. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The entire message to encrypt. - :Return: - a tuple with two byte strings: - - - the encrypted data - - the MAC - """ - - return self.encrypt(plaintext) + self.encrypt(), self.digest() - - def decrypt_and_verify(self, ciphertext, received_mac_tag): - """Decrypted the message and verify its authenticity in one step. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The entire message to decrypt. - received_mac_tag : byte string - This is the *binary* MAC, as received from the sender. - - :Return: the decrypted data (byte string). - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - plaintext = self.decrypt(ciphertext) + self.decrypt() - self.verify(received_mac_tag) - return plaintext - - -def _create_ocb_cipher(factory, **kwargs): - """Create a new block cipher, configured in OCB mode. - - :Parameters: - factory : module - A symmetric cipher module from `Crypto.Cipher` - (like `Crypto.Cipher.AES`). - - :Keywords: - nonce : bytes/bytearray/memoryview - A value that must never be reused for any other encryption. - Its length can vary from 1 to 15 bytes. - If not specified, a random 15 bytes long nonce is generated. - - mac_len : integer - Length of the MAC, in bytes. - It must be in the range ``[8..16]``. - The default is 16 (128 bits). - - Any other keyword will be passed to the underlying block cipher. - See the relevant documentation for details (at least ``key`` will need - to be present). - """ - - try: - nonce = kwargs.pop("nonce", None) - if nonce is None: - nonce = get_random_bytes(15) - mac_len = kwargs.pop("mac_len", 16) - except KeyError as e: - raise TypeError("Keyword missing: " + str(e)) - - return OcbMode(factory, nonce, mac_len, kwargs) diff --git a/Crypto/Cipher/_mode_ocb.pyi b/Crypto/Cipher/_mode_ocb.pyi deleted file mode 100644 index a1909fc..0000000 --- a/Crypto/Cipher/_mode_ocb.pyi +++ /dev/null @@ -1,36 +0,0 @@ -from types import ModuleType -from typing import Union, Any, Optional, Tuple, Dict, overload - -Buffer = Union[bytes, bytearray, memoryview] - -class OcbMode(object): - block_size: int - nonce: Buffer - - def __init__(self, - factory: ModuleType, - nonce: Buffer, - mac_len: int, - cipher_params: Dict) -> None: ... - - def update(self, assoc_data: Buffer) -> OcbMode: ... - - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, received_mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - - def encrypt_and_digest(self, - plaintext: Buffer) -> Tuple[bytes, bytes]: ... - def decrypt_and_verify(self, - ciphertext: Buffer, - received_mac_tag: Buffer) -> bytes: ... diff --git a/Crypto/Cipher/_mode_ofb.py b/Crypto/Cipher/_mode_ofb.py deleted file mode 100644 index 958f6d0..0000000 --- a/Crypto/Cipher/_mode_ofb.py +++ /dev/null @@ -1,282 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Cipher/mode_ofb.py : OFB mode -# -# =================================================================== -# 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. -# =================================================================== - -""" -Output Feedback (CFB) mode. -""" - -__all__ = ['OfbMode'] - -from Crypto.Util.py3compat import _copy_bytes -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - create_string_buffer, get_raw_buffer, - SmartPointer, c_size_t, c_uint8_ptr, - is_writeable_buffer) - -from Crypto.Random import get_random_bytes - -raw_ofb_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_ofb", """ - int OFB_start_operation(void *cipher, - const uint8_t iv[], - size_t iv_len, - void **pResult); - int OFB_encrypt(void *ofbState, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int OFB_decrypt(void *ofbState, - const uint8_t *in, - uint8_t *out, - size_t data_len); - int OFB_stop_operation(void *state); - """ - ) - - -class OfbMode(object): - """*Output FeedBack (OFB)*. - - This mode is very similar to CBC, but it - transforms the underlying block cipher into a stream cipher. - - The keystream is the iterated block encryption of the - previous ciphertext block. - - An Initialization Vector (*IV*) is required. - - See `NIST SP800-38A`_ , Section 6.4. - - .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - - :undocumented: __init__ - """ - - def __init__(self, block_cipher, iv): - """Create a new block cipher, configured in OFB mode. - - :Parameters: - block_cipher : C pointer - A smart pointer to the low-level block cipher instance. - - iv : bytes/bytearray/memoryview - The initialization vector to use for encryption or decryption. - It is as long as the cipher block. - - **The IV must be a nonce, to to be reused for any other - message**. It shall be a nonce or a random value. - - Reusing the *IV* for encryptions performed with the same key - compromises confidentiality. - """ - - self._state = VoidPointer() - result = raw_ofb_lib.OFB_start_operation(block_cipher.get(), - c_uint8_ptr(iv), - c_size_t(len(iv)), - self._state.address_of()) - if result: - raise ValueError("Error %d while instantiating the OFB mode" - % result) - - # Ensure that object disposal of this Python object will (eventually) - # free the memory allocated by the raw library for the cipher mode - self._state = SmartPointer(self._state.get(), - raw_ofb_lib.OFB_stop_operation) - - # Memory allocated for the underlying block cipher is now owed - # by the cipher mode - block_cipher.release() - - self.block_size = len(iv) - """The block size of the underlying cipher, in bytes.""" - - self.iv = _copy_bytes(None, None, iv) - """The Initialization Vector originally used to create the object. - The value does not change.""" - - self.IV = self.iv - """Alias for `iv`""" - - self._next = [ self.encrypt, self.decrypt ] - - def encrypt(self, plaintext, output=None): - """Encrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. - - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. - - That is, the statement: - - >>> c.encrypt(a) + c.encrypt(b) - - is equivalent to: - - >>> c.encrypt(a+b) - - This function does not add any padding to the plaintext. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - If ``output`` is ``None``, the ciphertext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if self.encrypt not in self._next: - raise TypeError("encrypt() cannot be called after decrypt()") - self._next = [ self.encrypt ] - - if output is None: - ciphertext = create_string_buffer(len(plaintext)) - else: - ciphertext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(plaintext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_ofb_lib.OFB_encrypt(self._state.get(), - c_uint8_ptr(plaintext), - c_uint8_ptr(ciphertext), - c_size_t(len(plaintext))) - if result: - raise ValueError("Error %d while encrypting in OFB mode" % result) - - if output is None: - return get_raw_buffer(ciphertext) - else: - return None - - def decrypt(self, ciphertext, output=None): - """Decrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. - - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. - - That is, the statement: - - >>> c.decrypt(a) + c.decrypt(b) - - is equivalent to: - - >>> c.decrypt(a+b) - - This function does not remove any padding from the plaintext. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - It can be of any length. - :Keywords: - output : bytearray/memoryview - The location where the plaintext is written to. - If ``None``, the plaintext is returned. - :Return: - If ``output`` is ``None``, the plaintext is returned as ``bytes``. - Otherwise, ``None``. - """ - - if self.decrypt not in self._next: - raise TypeError("decrypt() cannot be called after encrypt()") - self._next = [ self.decrypt ] - - if output is None: - plaintext = create_string_buffer(len(ciphertext)) - else: - plaintext = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(ciphertext) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(plaintext)) - - result = raw_ofb_lib.OFB_decrypt(self._state.get(), - c_uint8_ptr(ciphertext), - c_uint8_ptr(plaintext), - c_size_t(len(ciphertext))) - if result: - raise ValueError("Error %d while decrypting in OFB mode" % result) - - if output is None: - return get_raw_buffer(plaintext) - else: - return None - - -def _create_ofb_cipher(factory, **kwargs): - """Instantiate a cipher object that performs OFB encryption/decryption. - - :Parameters: - factory : module - The underlying block cipher, a module from ``Crypto.Cipher``. - - :Keywords: - iv : bytes/bytearray/memoryview - The IV to use for OFB. - - IV : bytes/bytearray/memoryview - Alias for ``iv``. - - Any other keyword will be passed to the underlying block cipher. - See the relevant documentation for details (at least ``key`` will need - to be present). - """ - - cipher_state = factory._create_base_cipher(kwargs) - iv = kwargs.pop("IV", None) - IV = kwargs.pop("iv", None) - - if (None, None) == (iv, IV): - iv = get_random_bytes(factory.block_size) - if iv is not None: - if IV is not None: - raise TypeError("You must either use 'iv' or 'IV', not both") - else: - iv = IV - - if len(iv) != factory.block_size: - raise ValueError("Incorrect IV length (it must be %d bytes long)" % - factory.block_size) - - if kwargs: - raise TypeError("Unknown parameters for OFB: %s" % str(kwargs)) - - return OfbMode(cipher_state, iv) diff --git a/Crypto/Cipher/_mode_ofb.pyi b/Crypto/Cipher/_mode_ofb.pyi deleted file mode 100644 index 60f7f00..0000000 --- a/Crypto/Cipher/_mode_ofb.pyi +++ /dev/null @@ -1,25 +0,0 @@ -from typing import Union, overload - -from Crypto.Util._raw_api import SmartPointer - -Buffer = Union[bytes, bytearray, memoryview] - -__all__ = ['OfbMode'] - -class OfbMode(object): - block_size: int - iv: Buffer - IV: Buffer - - def __init__(self, - block_cipher: SmartPointer, - iv: Buffer) -> None: ... - @overload - def encrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - @overload - def decrypt(self, plaintext: Buffer) -> bytes: ... - @overload - def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ... - diff --git a/Crypto/Cipher/_mode_openpgp.py b/Crypto/Cipher/_mode_openpgp.py deleted file mode 100644 index d079d59..0000000 --- a/Crypto/Cipher/_mode_openpgp.py +++ /dev/null @@ -1,206 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -""" -OpenPGP mode. -""" - -__all__ = ['OpenPgpMode'] - -from Crypto.Util.py3compat import _copy_bytes -from Crypto.Random import get_random_bytes - -class OpenPgpMode(object): - """OpenPGP mode. - - This mode is a variant of CFB, and it is only used in PGP and - OpenPGP_ applications. If in doubt, use another mode. - - An Initialization Vector (*IV*) is required. - - Unlike CFB, the *encrypted* IV (not the IV itself) is - transmitted to the receiver. - - The IV is a random data block. For legacy reasons, two of its bytes are - duplicated to act as a checksum for the correctness of the key, which is now - known to be insecure and is ignored. The encrypted IV is therefore 2 bytes - longer than the clean IV. - - .. _OpenPGP: http://tools.ietf.org/html/rfc4880 - - :undocumented: __init__ - """ - - def __init__(self, factory, key, iv, cipher_params): - - #: The block size of the underlying cipher, in bytes. - self.block_size = factory.block_size - - self._done_first_block = False # True after the first encryption - - # Instantiate a temporary cipher to process the IV - IV_cipher = factory.new( - key, - factory.MODE_CFB, - IV=b'\x00' * self.block_size, - segment_size=self.block_size * 8, - **cipher_params) - - iv = _copy_bytes(None, None, iv) - - # The cipher will be used for... - if len(iv) == self.block_size: - # ... encryption - self._encrypted_IV = IV_cipher.encrypt(iv + iv[-2:]) - elif len(iv) == self.block_size + 2: - # ... decryption - self._encrypted_IV = iv - # Last two bytes are for a deprecated "quick check" feature that - # should not be used. (https://eprint.iacr.org/2005/033) - iv = IV_cipher.decrypt(iv)[:-2] - else: - raise ValueError("Length of IV must be %d or %d bytes" - " for MODE_OPENPGP" - % (self.block_size, self.block_size + 2)) - - self.iv = self.IV = iv - - # Instantiate the cipher for the real PGP data - self._cipher = factory.new( - key, - factory.MODE_CFB, - IV=self._encrypted_IV[-self.block_size:], - segment_size=self.block_size * 8, - **cipher_params) - - def encrypt(self, plaintext): - """Encrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have encrypted a message - you cannot encrypt (or decrypt) another message using the same - object. - - The data to encrypt can be broken up in two or - more pieces and `encrypt` can be called multiple times. - - That is, the statement: - - >>> c.encrypt(a) + c.encrypt(b) - - is equivalent to: - - >>> c.encrypt(a+b) - - This function does not add any padding to the plaintext. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - - :Return: - the encrypted data, as a byte string. - It is as long as *plaintext* with one exception: - when encrypting the first message chunk, - the encypted IV is prepended to the returned ciphertext. - """ - - res = self._cipher.encrypt(plaintext) - if not self._done_first_block: - res = self._encrypted_IV + res - self._done_first_block = True - return res - - def decrypt(self, ciphertext): - """Decrypt data with the key and the parameters set at initialization. - - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. - - The data to decrypt can be broken up in two or - more pieces and `decrypt` can be called multiple times. - - That is, the statement: - - >>> c.decrypt(a) + c.decrypt(b) - - is equivalent to: - - >>> c.decrypt(a+b) - - This function does not remove any padding from the plaintext. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - - :Return: the decrypted data (byte string). - """ - - return self._cipher.decrypt(ciphertext) - - -def _create_openpgp_cipher(factory, **kwargs): - """Create a new block cipher, configured in OpenPGP mode. - - :Parameters: - factory : module - The module. - - :Keywords: - key : bytes/bytearray/memoryview - The secret key to use in the symmetric cipher. - - IV : bytes/bytearray/memoryview - The initialization vector to use for encryption or decryption. - - For encryption, the IV must be as long as the cipher block size. - - For decryption, it must be 2 bytes longer (it is actually the - *encrypted* IV which was prefixed to the ciphertext). - """ - - iv = kwargs.pop("IV", None) - IV = kwargs.pop("iv", None) - - if (None, None) == (iv, IV): - iv = get_random_bytes(factory.block_size) - if iv is not None: - if IV is not None: - raise TypeError("You must either use 'iv' or 'IV', not both") - else: - iv = IV - - try: - key = kwargs.pop("key") - except KeyError as e: - raise TypeError("Missing component: " + str(e)) - - return OpenPgpMode(factory, key, iv, kwargs) diff --git a/Crypto/Cipher/_mode_openpgp.pyi b/Crypto/Cipher/_mode_openpgp.pyi deleted file mode 100644 index 14b8105..0000000 --- a/Crypto/Cipher/_mode_openpgp.pyi +++ /dev/null @@ -1,20 +0,0 @@ -from types import ModuleType -from typing import Union, Dict - -Buffer = Union[bytes, bytearray, memoryview] - -__all__ = ['OpenPgpMode'] - -class OpenPgpMode(object): - block_size: int - iv: Union[bytes, bytearray, memoryview] - IV: Union[bytes, bytearray, memoryview] - - def __init__(self, - factory: ModuleType, - key: Buffer, - iv: Buffer, - cipher_params: Dict) -> None: ... - def encrypt(self, plaintext: Buffer) -> bytes: ... - def decrypt(self, plaintext: Buffer) -> bytes: ... - diff --git a/Crypto/Cipher/_mode_siv.py b/Crypto/Cipher/_mode_siv.py deleted file mode 100644 index d1eca2a..0000000 --- a/Crypto/Cipher/_mode_siv.py +++ /dev/null @@ -1,392 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -""" -Synthetic Initialization Vector (SIV) mode. -""" - -__all__ = ['SivMode'] - -from binascii import hexlify, unhexlify - -from Crypto.Util.py3compat import bord, _copy_bytes - -from Crypto.Util._raw_api import is_buffer - -from Crypto.Util.number import long_to_bytes, bytes_to_long -from Crypto.Protocol.KDF import _S2V -from Crypto.Hash import BLAKE2s -from Crypto.Random import get_random_bytes - - -class SivMode(object): - """Synthetic Initialization Vector (SIV). - - This is an Authenticated Encryption with Associated Data (`AEAD`_) mode. - It provides both confidentiality and authenticity. - - The header of the message may be left in the clear, if needed, and it will - still be subject to authentication. The decryption step tells the receiver - if the message comes from a source that really knowns the secret key. - Additionally, decryption detects if any part of the message - including the - header - has been modified or corrupted. - - Unlike other AEAD modes such as CCM, EAX or GCM, accidental reuse of a - nonce is not catastrophic for the confidentiality of the message. The only - effect is that an attacker can tell when the same plaintext (and same - associated data) is protected with the same key. - - The length of the MAC is fixed to the block size of the underlying cipher. - The key size is twice the length of the key of the underlying cipher. - - This mode is only available for AES ciphers. - - +--------------------+---------------+-------------------+ - | Cipher | SIV MAC size | SIV key length | - | | (bytes) | (bytes) | - +====================+===============+===================+ - | AES-128 | 16 | 32 | - +--------------------+---------------+-------------------+ - | AES-192 | 16 | 48 | - +--------------------+---------------+-------------------+ - | AES-256 | 16 | 64 | - +--------------------+---------------+-------------------+ - - See `RFC5297`_ and the `original paper`__. - - .. _RFC5297: https://tools.ietf.org/html/rfc5297 - .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html - .. __: http://www.cs.ucdavis.edu/~rogaway/papers/keywrap.pdf - - :undocumented: __init__ - """ - - def __init__(self, factory, key, nonce, kwargs): - - self.block_size = factory.block_size - """The block size of the underlying cipher, in bytes.""" - - self._factory = factory - - self._cipher_params = kwargs - - if len(key) not in (32, 48, 64): - raise ValueError("Incorrect key length (%d bytes)" % len(key)) - - if nonce is not None: - if not is_buffer(nonce): - raise TypeError("When provided, the nonce must be bytes, bytearray or memoryview") - - if len(nonce) == 0: - raise ValueError("When provided, the nonce must be non-empty") - - self.nonce = _copy_bytes(None, None, nonce) - """Public attribute is only available in case of non-deterministic - encryption.""" - - subkey_size = len(key) // 2 - - self._mac_tag = None # Cache for MAC tag - self._kdf = _S2V(key[:subkey_size], - ciphermod=factory, - cipher_params=self._cipher_params) - self._subkey_cipher = key[subkey_size:] - - # Purely for the purpose of verifying that cipher_params are OK - factory.new(key[:subkey_size], factory.MODE_ECB, **kwargs) - - # Allowed transitions after initialization - self._next = [self.update, self.encrypt, self.decrypt, - self.digest, self.verify] - - def _create_ctr_cipher(self, v): - """Create a new CTR cipher from V in SIV mode""" - - v_int = bytes_to_long(v) - q = v_int & 0xFFFFFFFFFFFFFFFF7FFFFFFF7FFFFFFF - return self._factory.new( - self._subkey_cipher, - self._factory.MODE_CTR, - initial_value=q, - nonce=b"", - **self._cipher_params) - - def update(self, component): - """Protect one associated data component - - For SIV, the associated data is a sequence (*vector*) of non-empty - byte strings (*components*). - - This method consumes the next component. It must be called - once for each of the components that constitue the associated data. - - Note that the components have clear boundaries, so that: - - >>> cipher.update(b"builtin") - >>> cipher.update(b"securely") - - is not equivalent to: - - >>> cipher.update(b"built") - >>> cipher.update(b"insecurely") - - If there is no associated data, this method must not be called. - - :Parameters: - component : bytes/bytearray/memoryview - The next associated data component. - """ - - if self.update not in self._next: - raise TypeError("update() can only be called" - " immediately after initialization") - - self._next = [self.update, self.encrypt, self.decrypt, - self.digest, self.verify] - - return self._kdf.update(component) - - def encrypt(self, plaintext): - """ - For SIV, encryption and MAC authentication must take place at the same - point. This method shall not be used. - - Use `encrypt_and_digest` instead. - """ - - raise TypeError("encrypt() not allowed for SIV mode." - " Use encrypt_and_digest() instead.") - - def decrypt(self, ciphertext): - """ - For SIV, decryption and verification must take place at the same - point. This method shall not be used. - - Use `decrypt_and_verify` instead. - """ - - raise TypeError("decrypt() not allowed for SIV mode." - " Use decrypt_and_verify() instead.") - - def digest(self): - """Compute the *binary* MAC tag. - - The caller invokes this function at the very end. - - This method returns the MAC that shall be sent to the receiver, - together with the ciphertext. - - :Return: the MAC, as a byte string. - """ - - if self.digest not in self._next: - raise TypeError("digest() cannot be called when decrypting" - " or validating a message") - self._next = [self.digest] - if self._mac_tag is None: - self._mac_tag = self._kdf.derive() - return self._mac_tag - - def hexdigest(self): - """Compute the *printable* MAC tag. - - This method is like `digest`. - - :Return: the MAC, as a hexadecimal string. - """ - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def verify(self, received_mac_tag): - """Validate the *binary* MAC tag. - - The caller invokes this function at the very end. - - This method checks if the decrypted message is indeed valid - (that is, if the key is correct) and it has not been - tampered with while in transit. - - :Parameters: - received_mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - if self.verify not in self._next: - raise TypeError("verify() cannot be called" - " when encrypting a message") - self._next = [self.verify] - - if self._mac_tag is None: - self._mac_tag = self._kdf.derive() - - secret = get_random_bytes(16) - - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag) - - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") - - def hexverify(self, hex_mac_tag): - """Validate the *printable* MAC tag. - - This method is like `verify`. - - :Parameters: - hex_mac_tag : string - This is the *printable* MAC, as received from the sender. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - self.verify(unhexlify(hex_mac_tag)) - - def encrypt_and_digest(self, plaintext, output=None): - """Perform encrypt() and digest() in one step. - - :Parameters: - plaintext : bytes/bytearray/memoryview - The piece of data to encrypt. - :Keywords: - output : bytearray/memoryview - The location where the ciphertext must be written to. - If ``None``, the ciphertext is returned. - :Return: - a tuple with two items: - - - the ciphertext, as ``bytes`` - - the MAC tag, as ``bytes`` - - The first item becomes ``None`` when the ``output`` parameter - specified a location for the result. - """ - - if self.encrypt not in self._next: - raise TypeError("encrypt() can only be called after" - " initialization or an update()") - - self._next = [ self.digest ] - - # Compute V (MAC) - if hasattr(self, 'nonce'): - self._kdf.update(self.nonce) - self._kdf.update(plaintext) - self._mac_tag = self._kdf.derive() - - cipher = self._create_ctr_cipher(self._mac_tag) - - return cipher.encrypt(plaintext, output=output), self._mac_tag - - def decrypt_and_verify(self, ciphertext, mac_tag, output=None): - """Perform decryption and verification in one step. - - A cipher object is stateful: once you have decrypted a message - you cannot decrypt (or encrypt) another message with the same - object. - - You cannot reuse an object for encrypting - or decrypting other data with the same key. - - This function does not remove any padding from the plaintext. - - :Parameters: - ciphertext : bytes/bytearray/memoryview - The piece of data to decrypt. - It can be of any length. - mac_tag : bytes/bytearray/memoryview - This is the *binary* MAC, as received from the sender. - :Keywords: - output : bytearray/memoryview - The location where the plaintext must be written to. - If ``None``, the plaintext is returned. - :Return: the plaintext as ``bytes`` or ``None`` when the ``output`` - parameter specified a location for the result. - :Raises ValueError: - if the MAC does not match. The message has been tampered with - or the key is incorrect. - """ - - if self.decrypt not in self._next: - raise TypeError("decrypt() can only be called" - " after initialization or an update()") - self._next = [ self.verify ] - - # Take the MAC and start the cipher for decryption - self._cipher = self._create_ctr_cipher(mac_tag) - - plaintext = self._cipher.decrypt(ciphertext, output=output) - - if hasattr(self, 'nonce'): - self._kdf.update(self.nonce) - self._kdf.update(plaintext if output is None else output) - self.verify(mac_tag) - - return plaintext - - -def _create_siv_cipher(factory, **kwargs): - """Create a new block cipher, configured in - Synthetic Initializaton Vector (SIV) mode. - - :Parameters: - - factory : object - A symmetric cipher module from `Crypto.Cipher` - (like `Crypto.Cipher.AES`). - - :Keywords: - - key : bytes/bytearray/memoryview - The secret key to use in the symmetric cipher. - It must be 32, 48 or 64 bytes long. - If AES is the chosen cipher, the variants *AES-128*, - *AES-192* and or *AES-256* will be used internally. - - nonce : bytes/bytearray/memoryview - For deterministic encryption, it is not present. - - Otherwise, it is a value that must never be reused - for encrypting message under this key. - - There are no restrictions on its length, - but it is recommended to use at least 16 bytes. - """ - - try: - key = kwargs.pop("key") - except KeyError as e: - raise TypeError("Missing parameter: " + str(e)) - - nonce = kwargs.pop("nonce", None) - - return SivMode(factory, key, nonce, kwargs) diff --git a/Crypto/Cipher/_mode_siv.pyi b/Crypto/Cipher/_mode_siv.pyi deleted file mode 100644 index 2934f23..0000000 --- a/Crypto/Cipher/_mode_siv.pyi +++ /dev/null @@ -1,38 +0,0 @@ -from types import ModuleType -from typing import Union, Tuple, Dict, Optional, overload - -Buffer = Union[bytes, bytearray, memoryview] - -__all__ = ['SivMode'] - -class SivMode(object): - block_size: int - nonce: bytes - - def __init__(self, - factory: ModuleType, - key: Buffer, - nonce: Buffer, - kwargs: Dict) -> None: ... - - def update(self, component: Buffer) -> SivMode: ... - - def encrypt(self, plaintext: Buffer) -> bytes: ... - def decrypt(self, plaintext: Buffer) -> bytes: ... - - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, received_mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - - @overload - def encrypt_and_digest(self, - plaintext: Buffer) -> Tuple[bytes, bytes]: ... - @overload - def encrypt_and_digest(self, - plaintext: Buffer, - output: Buffer) -> Tuple[None, bytes]: ... - def decrypt_and_verify(self, - ciphertext: Buffer, - received_mac_tag: Buffer, - output: Optional[Union[bytearray, memoryview]] = ...) -> bytes: ... diff --git a/Crypto/Cipher/_raw_aes.abi3.so b/Crypto/Cipher/_raw_aes.abi3.so deleted file mode 100644 index 7bc3d39..0000000 Binary files a/Crypto/Cipher/_raw_aes.abi3.so and /dev/null differ diff --git a/Crypto/Cipher/_raw_aesni.abi3.so b/Crypto/Cipher/_raw_aesni.abi3.so deleted file mode 100644 index 88be608..0000000 Binary files a/Crypto/Cipher/_raw_aesni.abi3.so and /dev/null differ diff --git a/Crypto/Cipher/_raw_arc2.abi3.so b/Crypto/Cipher/_raw_arc2.abi3.so deleted file mode 100644 index 49f9763..0000000 Binary files a/Crypto/Cipher/_raw_arc2.abi3.so and /dev/null differ diff --git a/Crypto/Cipher/_raw_blowfish.abi3.so b/Crypto/Cipher/_raw_blowfish.abi3.so deleted file mode 100644 index 900a509..0000000 Binary files a/Crypto/Cipher/_raw_blowfish.abi3.so and /dev/null differ diff --git a/Crypto/Cipher/_raw_cast.abi3.so b/Crypto/Cipher/_raw_cast.abi3.so deleted file mode 100644 index 0aabbe8..0000000 Binary files a/Crypto/Cipher/_raw_cast.abi3.so and /dev/null differ diff --git a/Crypto/Cipher/_raw_cbc.abi3.so b/Crypto/Cipher/_raw_cbc.abi3.so deleted file mode 100644 index d39e172..0000000 Binary files a/Crypto/Cipher/_raw_cbc.abi3.so and /dev/null differ diff --git a/Crypto/Cipher/_raw_cfb.abi3.so b/Crypto/Cipher/_raw_cfb.abi3.so deleted file mode 100644 index 96dd44d..0000000 Binary files a/Crypto/Cipher/_raw_cfb.abi3.so and /dev/null differ diff --git a/Crypto/Cipher/_raw_ctr.abi3.so b/Crypto/Cipher/_raw_ctr.abi3.so deleted file mode 100644 index e5a71de..0000000 Binary files a/Crypto/Cipher/_raw_ctr.abi3.so and /dev/null differ diff --git a/Crypto/Cipher/_raw_des.abi3.so b/Crypto/Cipher/_raw_des.abi3.so deleted file mode 100644 index a250e3a..0000000 Binary files a/Crypto/Cipher/_raw_des.abi3.so and /dev/null differ diff --git a/Crypto/Cipher/_raw_des3.abi3.so b/Crypto/Cipher/_raw_des3.abi3.so deleted file mode 100644 index ba68b32..0000000 Binary files a/Crypto/Cipher/_raw_des3.abi3.so and /dev/null differ diff --git a/Crypto/Cipher/_raw_ecb.abi3.so b/Crypto/Cipher/_raw_ecb.abi3.so deleted file mode 100644 index fd47fed..0000000 Binary files a/Crypto/Cipher/_raw_ecb.abi3.so and /dev/null differ diff --git a/Crypto/Cipher/_raw_eksblowfish.abi3.so b/Crypto/Cipher/_raw_eksblowfish.abi3.so deleted file mode 100644 index a20c0b0..0000000 Binary files a/Crypto/Cipher/_raw_eksblowfish.abi3.so and /dev/null differ diff --git a/Crypto/Cipher/_raw_ocb.abi3.so b/Crypto/Cipher/_raw_ocb.abi3.so deleted file mode 100644 index 3af24e6..0000000 Binary files a/Crypto/Cipher/_raw_ocb.abi3.so and /dev/null differ diff --git a/Crypto/Cipher/_raw_ofb.abi3.so b/Crypto/Cipher/_raw_ofb.abi3.so deleted file mode 100644 index 732caf6..0000000 Binary files a/Crypto/Cipher/_raw_ofb.abi3.so and /dev/null differ diff --git a/Crypto/Hash/BLAKE2b.py b/Crypto/Hash/BLAKE2b.py deleted file mode 100644 index a00e0b4..0000000 --- a/Crypto/Hash/BLAKE2b.py +++ /dev/null @@ -1,247 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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 binascii import unhexlify - -from Crypto.Util.py3compat import bord, tobytes - -from Crypto.Random import get_random_bytes -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_blake2b_lib = load_pycryptodome_raw_lib("Crypto.Hash._BLAKE2b", - """ - int blake2b_init(void **state, - const uint8_t *key, - size_t key_size, - size_t digest_size); - int blake2b_destroy(void *state); - int blake2b_update(void *state, - const uint8_t *buf, - size_t len); - int blake2b_digest(const void *state, - uint8_t digest[64]); - int blake2b_copy(const void *src, void *dst); - """) - - -class BLAKE2b_Hash(object): - """A BLAKE2b hash object. - Do not instantiate directly. Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The internal block size of the hash algorithm in bytes. - block_size = 64 - - def __init__(self, data, key, digest_bytes, update_after_digest): - - # The size of the resulting hash in bytes. - self.digest_size = digest_bytes - - self._update_after_digest = update_after_digest - self._digest_done = False - - # See https://tools.ietf.org/html/rfc7693 - if digest_bytes in (20, 32, 48, 64) and not key: - self.oid = "1.3.6.1.4.1.1722.12.2.1." + str(digest_bytes) - - state = VoidPointer() - result = _raw_blake2b_lib.blake2b_init(state.address_of(), - c_uint8_ptr(key), - c_size_t(len(key)), - c_size_t(digest_bytes) - ) - if result: - raise ValueError("Error %d while instantiating BLAKE2b" % result) - self._state = SmartPointer(state.get(), - _raw_blake2b_lib.blake2b_destroy) - if data: - self.update(data) - - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (bytes/bytearray/memoryview): The next chunk of the message being hashed. - """ - - if self._digest_done and not self._update_after_digest: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - - result = _raw_blake2b_lib.blake2b_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while hashing BLAKE2b data" % result) - return self - - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(64) - result = _raw_blake2b_lib.blake2b_digest(self._state.get(), - bfr) - if result: - raise ValueError("Error %d while creating BLAKE2b digest" % result) - - self._digest_done = True - - return get_raw_buffer(bfr)[:self.digest_size] - - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) - - - def verify(self, mac_tag): - """Verify that a given **binary** MAC (computed by another party) - is valid. - - Args: - mac_tag (bytes/bytearray/memoryview): the expected MAC of the message. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - secret = get_random_bytes(16) - - mac1 = new(digest_bits=160, key=secret, data=mac_tag) - mac2 = new(digest_bits=160, key=secret, data=self.digest()) - - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") - - - def hexverify(self, hex_mac_tag): - """Verify that a given **printable** MAC (computed by another party) - is valid. - - Args: - hex_mac_tag (string): the expected MAC of the message, as a hexadecimal string. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - self.verify(unhexlify(tobytes(hex_mac_tag))) - - - def new(self, **kwargs): - """Return a new instance of a BLAKE2b hash object. - See :func:`new`. - """ - - if "digest_bytes" not in kwargs and "digest_bits" not in kwargs: - kwargs["digest_bytes"] = self.digest_size - - return new(**kwargs) - - -def new(**kwargs): - """Create a new hash object. - - Args: - data (bytes/bytearray/memoryview): - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`BLAKE2b_Hash.update`. - digest_bytes (integer): - Optional. The size of the digest, in bytes (1 to 64). Default is 64. - digest_bits (integer): - Optional and alternative to ``digest_bytes``. - The size of the digest, in bits (8 to 512, in steps of 8). - Default is 512. - key (bytes/bytearray/memoryview): - Optional. The key to use to compute the MAC (1 to 64 bytes). - If not specified, no key will be used. - update_after_digest (boolean): - Optional. By default, a hash object cannot be updated anymore after - the digest is computed. When this flag is ``True``, such check - is no longer enforced. - - Returns: - A :class:`BLAKE2b_Hash` hash object - """ - - data = kwargs.pop("data", None) - update_after_digest = kwargs.pop("update_after_digest", False) - - digest_bytes = kwargs.pop("digest_bytes", None) - digest_bits = kwargs.pop("digest_bits", None) - if None not in (digest_bytes, digest_bits): - raise TypeError("Only one digest parameter must be provided") - if (None, None) == (digest_bytes, digest_bits): - digest_bytes = 64 - if digest_bytes is not None: - if not (1 <= digest_bytes <= 64): - raise ValueError("'digest_bytes' not in range 1..64") - else: - if not (8 <= digest_bits <= 512) or (digest_bits % 8): - raise ValueError("'digest_bytes' not in range 8..512, " - "with steps of 8") - digest_bytes = digest_bits // 8 - - key = kwargs.pop("key", b"") - if len(key) > 64: - raise ValueError("BLAKE2s key cannot exceed 64 bytes") - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return BLAKE2b_Hash(data, key, digest_bytes, update_after_digest) diff --git a/Crypto/Hash/BLAKE2b.pyi b/Crypto/Hash/BLAKE2b.pyi deleted file mode 100644 index ac3bf57..0000000 --- a/Crypto/Hash/BLAKE2b.pyi +++ /dev/null @@ -1,31 +0,0 @@ -from typing import Any, Union - -Buffer = Union[bytes, bytearray, memoryview] - -class BLAKE2b_Hash(object): - block_size: int - digest_size: int - oid: str - - def __init__(self, - data: Buffer, - key: Buffer, - digest_bytes: bytes, - update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> BLAKE2b_Hash: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - def new(self, - data: Buffer = ..., - digest_bytes: int = ..., - digest_bits: int = ..., - key: Buffer = ..., - update_after_digest: bool = ...) -> BLAKE2b_Hash: ... - -def new(data: Buffer = ..., - digest_bytes: int = ..., - digest_bits: int = ..., - key: Buffer = ..., - update_after_digest: bool = ...) -> BLAKE2b_Hash: ... diff --git a/Crypto/Hash/BLAKE2s.py b/Crypto/Hash/BLAKE2s.py deleted file mode 100644 index 9b25c4a..0000000 --- a/Crypto/Hash/BLAKE2s.py +++ /dev/null @@ -1,247 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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 binascii import unhexlify - -from Crypto.Util.py3compat import bord, tobytes - -from Crypto.Random import get_random_bytes -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_blake2s_lib = load_pycryptodome_raw_lib("Crypto.Hash._BLAKE2s", - """ - int blake2s_init(void **state, - const uint8_t *key, - size_t key_size, - size_t digest_size); - int blake2s_destroy(void *state); - int blake2s_update(void *state, - const uint8_t *buf, - size_t len); - int blake2s_digest(const void *state, - uint8_t digest[32]); - int blake2s_copy(const void *src, void *dst); - """) - - -class BLAKE2s_Hash(object): - """A BLAKE2s hash object. - Do not instantiate directly. Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The internal block size of the hash algorithm in bytes. - block_size = 32 - - def __init__(self, data, key, digest_bytes, update_after_digest): - - # The size of the resulting hash in bytes. - self.digest_size = digest_bytes - - self._update_after_digest = update_after_digest - self._digest_done = False - - # See https://tools.ietf.org/html/rfc7693 - if digest_bytes in (16, 20, 28, 32) and not key: - self.oid = "1.3.6.1.4.1.1722.12.2.2." + str(digest_bytes) - - state = VoidPointer() - result = _raw_blake2s_lib.blake2s_init(state.address_of(), - c_uint8_ptr(key), - c_size_t(len(key)), - c_size_t(digest_bytes) - ) - if result: - raise ValueError("Error %d while instantiating BLAKE2s" % result) - self._state = SmartPointer(state.get(), - _raw_blake2s_lib.blake2s_destroy) - if data: - self.update(data) - - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._digest_done and not self._update_after_digest: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - - result = _raw_blake2s_lib.blake2s_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while hashing BLAKE2s data" % result) - return self - - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(32) - result = _raw_blake2s_lib.blake2s_digest(self._state.get(), - bfr) - if result: - raise ValueError("Error %d while creating BLAKE2s digest" % result) - - self._digest_done = True - - return get_raw_buffer(bfr)[:self.digest_size] - - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in tuple(self.digest())]) - - - def verify(self, mac_tag): - """Verify that a given **binary** MAC (computed by another party) - is valid. - - Args: - mac_tag (byte string/byte array/memoryview): the expected MAC of the message. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - secret = get_random_bytes(16) - - mac1 = new(digest_bits=160, key=secret, data=mac_tag) - mac2 = new(digest_bits=160, key=secret, data=self.digest()) - - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") - - - def hexverify(self, hex_mac_tag): - """Verify that a given **printable** MAC (computed by another party) - is valid. - - Args: - hex_mac_tag (string): the expected MAC of the message, as a hexadecimal string. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - self.verify(unhexlify(tobytes(hex_mac_tag))) - - - def new(self, **kwargs): - """Return a new instance of a BLAKE2s hash object. - See :func:`new`. - """ - - if "digest_bytes" not in kwargs and "digest_bits" not in kwargs: - kwargs["digest_bytes"] = self.digest_size - - return new(**kwargs) - - -def new(**kwargs): - """Create a new hash object. - - Args: - data (byte string/byte array/memoryview): - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`BLAKE2s_Hash.update`. - digest_bytes (integer): - Optional. The size of the digest, in bytes (1 to 32). Default is 32. - digest_bits (integer): - Optional and alternative to ``digest_bytes``. - The size of the digest, in bits (8 to 256, in steps of 8). - Default is 256. - key (byte string): - Optional. The key to use to compute the MAC (1 to 64 bytes). - If not specified, no key will be used. - update_after_digest (boolean): - Optional. By default, a hash object cannot be updated anymore after - the digest is computed. When this flag is ``True``, such check - is no longer enforced. - - Returns: - A :class:`BLAKE2s_Hash` hash object - """ - - data = kwargs.pop("data", None) - update_after_digest = kwargs.pop("update_after_digest", False) - - digest_bytes = kwargs.pop("digest_bytes", None) - digest_bits = kwargs.pop("digest_bits", None) - if None not in (digest_bytes, digest_bits): - raise TypeError("Only one digest parameter must be provided") - if (None, None) == (digest_bytes, digest_bits): - digest_bytes = 32 - if digest_bytes is not None: - if not (1 <= digest_bytes <= 32): - raise ValueError("'digest_bytes' not in range 1..32") - else: - if not (8 <= digest_bits <= 256) or (digest_bits % 8): - raise ValueError("'digest_bytes' not in range 8..256, " - "with steps of 8") - digest_bytes = digest_bits // 8 - - key = kwargs.pop("key", b"") - if len(key) > 32: - raise ValueError("BLAKE2s key cannot exceed 32 bytes") - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return BLAKE2s_Hash(data, key, digest_bytes, update_after_digest) diff --git a/Crypto/Hash/BLAKE2s.pyi b/Crypto/Hash/BLAKE2s.pyi deleted file mode 100644 index 374b3a4..0000000 --- a/Crypto/Hash/BLAKE2s.pyi +++ /dev/null @@ -1,26 +0,0 @@ -from typing import Any, Union - -Buffer = Union[bytes, bytearray, memoryview] - -class BLAKE2s_Hash(object): - block_size: int - digest_size: int - oid: str - - def __init__(self, - data: Buffer, - key: Buffer, - digest_bytes: bytes, - update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> BLAKE2s_Hash: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - def new(self, **kwargs: Any) -> BLAKE2s_Hash: ... - -def new(data: Buffer = ..., - digest_bytes: int = ..., - digest_bits: int = ..., - key: Buffer = ..., - update_after_digest: bool = ...) -> BLAKE2s_Hash: ... diff --git a/Crypto/Hash/CMAC.py b/Crypto/Hash/CMAC.py deleted file mode 100644 index 7585617..0000000 --- a/Crypto/Hash/CMAC.py +++ /dev/null @@ -1,302 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Hash/CMAC.py - Implements the CMAC algorithm -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -from binascii import unhexlify - -from Crypto.Hash import BLAKE2s -from Crypto.Util.strxor import strxor -from Crypto.Util.number import long_to_bytes, bytes_to_long -from Crypto.Util.py3compat import bord, tobytes, _copy_bytes -from Crypto.Random import get_random_bytes - - -# The size of the authentication tag produced by the MAC. -digest_size = None - - -def _shift_bytes(bs, xor_lsb=0): - num = (bytes_to_long(bs) << 1) ^ xor_lsb - return long_to_bytes(num, len(bs))[-len(bs):] - - -class CMAC(object): - """A CMAC hash object. - Do not instantiate directly. Use the :func:`new` function. - - :ivar digest_size: the size in bytes of the resulting MAC tag - :vartype digest_size: integer - """ - - digest_size = None - - def __init__(self, key, msg, ciphermod, cipher_params, mac_len, - update_after_digest): - - self.digest_size = mac_len - - self._key = _copy_bytes(None, None, key) - self._factory = ciphermod - self._cipher_params = cipher_params - self._block_size = bs = ciphermod.block_size - self._mac_tag = None - self._update_after_digest = update_after_digest - - # Section 5.3 of NIST SP 800 38B and Appendix B - if bs == 8: - const_Rb = 0x1B - self._max_size = 8 * (2 ** 21) - elif bs == 16: - const_Rb = 0x87 - self._max_size = 16 * (2 ** 48) - else: - raise TypeError("CMAC requires a cipher with a block size" - " of 8 or 16 bytes, not %d" % bs) - - # Compute sub-keys - zero_block = b'\x00' * bs - self._ecb = ciphermod.new(key, - ciphermod.MODE_ECB, - **self._cipher_params) - L = self._ecb.encrypt(zero_block) - if bord(L[0]) & 0x80: - self._k1 = _shift_bytes(L, const_Rb) - else: - self._k1 = _shift_bytes(L) - if bord(self._k1[0]) & 0x80: - self._k2 = _shift_bytes(self._k1, const_Rb) - else: - self._k2 = _shift_bytes(self._k1) - - # Initialize CBC cipher with zero IV - self._cbc = ciphermod.new(key, - ciphermod.MODE_CBC, - zero_block, - **self._cipher_params) - - # Cache for outstanding data to authenticate - self._cache = bytearray(bs) - self._cache_n = 0 - - # Last piece of ciphertext produced - self._last_ct = zero_block - - # Last block that was encrypted with AES - self._last_pt = None - - # Counter for total message size - self._data_size = 0 - - if msg: - self.update(msg) - - def update(self, msg): - """Authenticate the next chunk of message. - - Args: - data (byte string/byte array/memoryview): The next chunk of data - """ - - if self._mac_tag is not None and not self._update_after_digest: - raise TypeError("update() cannot be called after digest() or verify()") - - self._data_size += len(msg) - bs = self._block_size - - if self._cache_n > 0: - filler = min(bs - self._cache_n, len(msg)) - self._cache[self._cache_n:self._cache_n+filler] = msg[:filler] - self._cache_n += filler - - if self._cache_n < bs: - return self - - msg = memoryview(msg)[filler:] - self._update(self._cache) - self._cache_n = 0 - - remain = len(msg) % bs - if remain > 0: - self._update(msg[:-remain]) - self._cache[:remain] = msg[-remain:] - else: - self._update(msg) - self._cache_n = remain - return self - - def _update(self, data_block): - """Update a block aligned to the block boundary""" - - bs = self._block_size - assert len(data_block) % bs == 0 - - if len(data_block) == 0: - return - - ct = self._cbc.encrypt(data_block) - if len(data_block) == bs: - second_last = self._last_ct - else: - second_last = ct[-bs*2:-bs] - self._last_ct = ct[-bs:] - self._last_pt = strxor(second_last, data_block[-bs:]) - - def copy(self): - """Return a copy ("clone") of the CMAC object. - - The copy will have the same internal state as the original CMAC - object. - This can be used to efficiently compute the MAC tag of byte - strings that share a common initial substring. - - :return: An :class:`CMAC` - """ - - obj = self.__new__(CMAC) - obj.__dict__ = self.__dict__.copy() - obj._cbc = self._factory.new(self._key, - self._factory.MODE_CBC, - self._last_ct, - **self._cipher_params) - obj._cache = self._cache[:] - obj._last_ct = self._last_ct[:] - return obj - - def digest(self): - """Return the **binary** (non-printable) MAC tag of the message - that has been authenticated so far. - - :return: The MAC tag, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bs = self._block_size - - if self._mac_tag is not None and not self._update_after_digest: - return self._mac_tag - - if self._data_size > self._max_size: - raise ValueError("MAC is unsafe for this message") - - if self._cache_n == 0 and self._data_size > 0: - # Last block was full - pt = strxor(self._last_pt, self._k1) - else: - # Last block is partial (or message length is zero) - partial = self._cache[:] - partial[self._cache_n:] = b'\x80' + b'\x00' * (bs - self._cache_n - 1) - pt = strxor(strxor(self._last_ct, partial), self._k2) - - self._mac_tag = self._ecb.encrypt(pt)[:self.digest_size] - - return self._mac_tag - - def hexdigest(self): - """Return the **printable** MAC tag of the message authenticated so far. - - :return: The MAC tag, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) - for x in tuple(self.digest())]) - - def verify(self, mac_tag): - """Verify that a given **binary** MAC (computed by another party) - is valid. - - Args: - mac_tag (byte string/byte array/memoryview): the expected MAC of the message. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - secret = get_random_bytes(16) - - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest()) - - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") - - def hexverify(self, hex_mac_tag): - """Return the **printable** MAC tag of the message authenticated so far. - - :return: The MAC tag, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - self.verify(unhexlify(tobytes(hex_mac_tag))) - - -def new(key, msg=None, ciphermod=None, cipher_params=None, mac_len=None, - update_after_digest=False): - """Create a new MAC object. - - Args: - key (byte string/byte array/memoryview): - key for the CMAC object. - The key must be valid for the underlying cipher algorithm. - For instance, it must be 16 bytes long for AES-128. - ciphermod (module): - A cipher module from :mod:`Crypto.Cipher`. - The cipher's block size has to be 128 bits, - like :mod:`Crypto.Cipher.AES`, to reduce the probability - of collisions. - msg (byte string/byte array/memoryview): - Optional. The very first chunk of the message to authenticate. - It is equivalent to an early call to `CMAC.update`. Optional. - cipher_params (dict): - Optional. A set of parameters to use when instantiating a cipher - object. - mac_len (integer): - Length of the MAC, in bytes. - It must be at least 4 bytes long. - The default (and recommended) length matches the size of a cipher block. - update_after_digest (boolean): - Optional. By default, a hash object cannot be updated anymore after - the digest is computed. When this flag is ``True``, such check - is no longer enforced. - Returns: - A :class:`CMAC` object - """ - - if ciphermod is None: - raise TypeError("ciphermod must be specified (try AES)") - - cipher_params = {} if cipher_params is None else dict(cipher_params) - - if mac_len is None: - mac_len = ciphermod.block_size - - if mac_len < 4: - raise ValueError("MAC tag length must be at least 4 bytes long") - - if mac_len > ciphermod.block_size: - raise ValueError("MAC tag length cannot be larger than a cipher block (%d) bytes" % ciphermod.block_size) - - return CMAC(key, msg, ciphermod, cipher_params, mac_len, - update_after_digest) diff --git a/Crypto/Hash/CMAC.pyi b/Crypto/Hash/CMAC.pyi deleted file mode 100644 index 33773aa..0000000 --- a/Crypto/Hash/CMAC.pyi +++ /dev/null @@ -1,30 +0,0 @@ -from types import ModuleType -from typing import Union, Dict - -Buffer = Union[bytes, bytearray, memoryview] - -digest_size: int - -class CMAC(object): - digest_size: int - - def __init__(self, - key: Buffer, - msg: Buffer, - ciphermod: ModuleType, - cipher_params: dict, - mac_len: int, update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> CMAC: ... - def copy(self) -> CMAC: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - - -def new(key: Buffer, - msg: Buffer = ..., - ciphermod: ModuleType = ..., - cipher_params: Dict = ..., - mac_len: int = ..., - update_after_digest: bool = ...) -> CMAC: ... diff --git a/Crypto/Hash/HMAC.py b/Crypto/Hash/HMAC.py deleted file mode 100644 index e82bb9d..0000000 --- a/Crypto/Hash/HMAC.py +++ /dev/null @@ -1,213 +0,0 @@ -# -# HMAC.py - Implements the HMAC algorithm as described by RFC 2104. -# -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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 Crypto.Util.py3compat import bord, tobytes - -from binascii import unhexlify - -from Crypto.Hash import MD5 -from Crypto.Hash import BLAKE2s -from Crypto.Util.strxor import strxor -from Crypto.Random import get_random_bytes - -__all__ = ['new', 'HMAC'] - - -class HMAC(object): - """An HMAC hash object. - Do not instantiate directly. Use the :func:`new` function. - - :ivar digest_size: the size in bytes of the resulting MAC tag - :vartype digest_size: integer - """ - - def __init__(self, key, msg=b"", digestmod=None): - - if digestmod is None: - digestmod = MD5 - - if msg is None: - msg = b"" - - # Size of the MAC tag - self.digest_size = digestmod.digest_size - - self._digestmod = digestmod - - if isinstance(key, memoryview): - key = key.tobytes() - - try: - if len(key) <= digestmod.block_size: - # Step 1 or 2 - key_0 = key + b"\x00" * (digestmod.block_size - len(key)) - else: - # Step 3 - hash_k = digestmod.new(key).digest() - key_0 = hash_k + b"\x00" * (digestmod.block_size - len(hash_k)) - except AttributeError: - # Not all hash types have "block_size" - raise ValueError("Hash type incompatible to HMAC") - - # Step 4 - key_0_ipad = strxor(key_0, b"\x36" * len(key_0)) - - # Start step 5 and 6 - self._inner = digestmod.new(key_0_ipad) - self._inner.update(msg) - - # Step 7 - key_0_opad = strxor(key_0, b"\x5c" * len(key_0)) - - # Start step 8 and 9 - self._outer = digestmod.new(key_0_opad) - - def update(self, msg): - """Authenticate the next chunk of message. - - Args: - data (byte string/byte array/memoryview): The next chunk of data - """ - - self._inner.update(msg) - return self - - def _pbkdf2_hmac_assist(self, first_digest, iterations): - """Carry out the expensive inner loop for PBKDF2-HMAC""" - - result = self._digestmod._pbkdf2_hmac_assist( - self._inner, - self._outer, - first_digest, - iterations) - return result - - def copy(self): - """Return a copy ("clone") of the HMAC object. - - The copy will have the same internal state as the original HMAC - object. - This can be used to efficiently compute the MAC tag of byte - strings that share a common initial substring. - - :return: An :class:`HMAC` - """ - - new_hmac = HMAC(b"fake key", digestmod=self._digestmod) - - # Syncronize the state - new_hmac._inner = self._inner.copy() - new_hmac._outer = self._outer.copy() - - return new_hmac - - def digest(self): - """Return the **binary** (non-printable) MAC tag of the message - authenticated so far. - - :return: The MAC tag digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - frozen_outer_hash = self._outer.copy() - frozen_outer_hash.update(self._inner.digest()) - return frozen_outer_hash.digest() - - def verify(self, mac_tag): - """Verify that a given **binary** MAC (computed by another party) - is valid. - - Args: - mac_tag (byte string/byte string/memoryview): the expected MAC of the message. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - secret = get_random_bytes(16) - - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest()) - - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") - - def hexdigest(self): - """Return the **printable** MAC tag of the message authenticated so far. - - :return: The MAC tag, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) - for x in tuple(self.digest())]) - - def hexverify(self, hex_mac_tag): - """Verify that a given **printable** MAC (computed by another party) - is valid. - - Args: - hex_mac_tag (string): the expected MAC of the message, - as a hexadecimal string. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - self.verify(unhexlify(tobytes(hex_mac_tag))) - - -def new(key, msg=b"", digestmod=None): - """Create a new MAC object. - - Args: - key (bytes/bytearray/memoryview): - key for the MAC object. - It must be long enough to match the expected security level of the - MAC. - msg (bytes/bytearray/memoryview): - Optional. The very first chunk of the message to authenticate. - It is equivalent to an early call to :meth:`HMAC.update`. - digestmod (module): - The hash to use to implement the HMAC. - Default is :mod:`Crypto.Hash.MD5`. - - Returns: - An :class:`HMAC` object - """ - - return HMAC(key, msg, digestmod) diff --git a/Crypto/Hash/HMAC.pyi b/Crypto/Hash/HMAC.pyi deleted file mode 100644 index b577230..0000000 --- a/Crypto/Hash/HMAC.pyi +++ /dev/null @@ -1,25 +0,0 @@ -from types import ModuleType -from typing import Union, Dict - -Buffer = Union[bytes, bytearray, memoryview] - -digest_size: int - -class HMAC(object): - digest_size: int - - def __init__(self, - key: Buffer, - msg: Buffer, - digestmod: ModuleType) -> None: ... - def update(self, msg: Buffer) -> HMAC: ... - def copy(self) -> HMAC: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - - -def new(key: Buffer, - msg: Buffer = ..., - digestmod: ModuleType = ...) -> HMAC: ... diff --git a/Crypto/Hash/MD2.py b/Crypto/Hash/MD2.py deleted file mode 100644 index 41decbb..0000000 --- a/Crypto/Hash/MD2.py +++ /dev/null @@ -1,166 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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 Crypto.Util.py3compat import bord - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_md2_lib = load_pycryptodome_raw_lib( - "Crypto.Hash._MD2", - """ - int md2_init(void **shaState); - int md2_destroy(void *shaState); - int md2_update(void *hs, - const uint8_t *buf, - size_t len); - int md2_digest(const void *shaState, - uint8_t digest[20]); - int md2_copy(const void *src, void *dst); - """) - - -class MD2Hash(object): - """An MD2 hash object. - Do not instantiate directly. Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 16 - # The internal block size of the hash algorithm in bytes. - block_size = 16 - # ASN.1 Object ID - oid = "1.2.840.113549.2.2" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_md2_lib.md2_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating MD2" - % result) - self._state = SmartPointer(state.get(), - _raw_md2_lib.md2_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_md2_lib.md2_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while instantiating MD2" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_md2_lib.md2_digest(self._state.get(), - bfr) - if result: - raise ValueError("Error %d while instantiating MD2" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = MD2Hash() - result = _raw_md2_lib.md2_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying MD2" % result) - return clone - - def new(self, data=None): - return MD2Hash(data) - - -def new(data=None): - """Create a new hash object. - - :parameter data: - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`MD2Hash.update`. - :type data: bytes/bytearray/memoryview - - :Return: A :class:`MD2Hash` hash object - """ - - return MD2Hash().new(data) - -# The size of the resulting hash in bytes. -digest_size = MD2Hash.digest_size - -# The internal block size of the hash algorithm in bytes. -block_size = MD2Hash.block_size diff --git a/Crypto/Hash/MD2.pyi b/Crypto/Hash/MD2.pyi deleted file mode 100644 index 95a97a9..0000000 --- a/Crypto/Hash/MD2.pyi +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Union - -Buffer = Union[bytes, bytearray, memoryview] - -class MD4Hash(object): - digest_size: int - block_size: int - oid: str - - def __init__(self, data: Buffer = ...) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> MD4Hash: ... - def new(self, data: Buffer = ...) -> MD4Hash: ... - -def new(data: Buffer = ...) -> MD4Hash: ... -digest_size: int -block_size: int diff --git a/Crypto/Hash/MD4.py b/Crypto/Hash/MD4.py deleted file mode 100644 index be12b19..0000000 --- a/Crypto/Hash/MD4.py +++ /dev/null @@ -1,185 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -""" -MD4 is specified in RFC1320_ and produces the 128 bit digest of a message. - - >>> from Crypto.Hash import MD4 - >>> - >>> h = MD4.new() - >>> h.update(b'Hello') - >>> print h.hexdigest() - -MD4 stand for Message Digest version 4, and it was invented by Rivest in 1990. -This algorithm is insecure. Do not use it for new designs. - -.. _RFC1320: http://tools.ietf.org/html/rfc1320 -""" - -from Crypto.Util.py3compat import bord - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_md4_lib = load_pycryptodome_raw_lib( - "Crypto.Hash._MD4", - """ - int md4_init(void **shaState); - int md4_destroy(void *shaState); - int md4_update(void *hs, - const uint8_t *buf, - size_t len); - int md4_digest(const void *shaState, - uint8_t digest[20]); - int md4_copy(const void *src, void *dst); - """) - - -class MD4Hash(object): - """Class that implements an MD4 hash - """ - - #: The size of the resulting hash in bytes. - digest_size = 16 - #: The internal block size of the hash algorithm in bytes. - block_size = 64 - #: ASN.1 Object ID - oid = "1.2.840.113549.2.4" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_md4_lib.md4_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating MD4" - % result) - self._state = SmartPointer(state.get(), - _raw_md4_lib.md4_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Repeated calls are equivalent to a single call with the concatenation - of all the arguments. In other words: - - >>> m.update(a); m.update(b) - - is equivalent to: - - >>> m.update(a+b) - - :Parameters: - data : byte string/byte array/memoryview - The next chunk of the message being hashed. - """ - - result = _raw_md4_lib.md4_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while instantiating MD4" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that - has been hashed so far. - - This method does not change the state of the hash object. - You can continue updating the object after calling this function. - - :Return: A byte string of `digest_size` bytes. It may contain non-ASCII - characters, including null bytes. - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_md4_lib.md4_digest(self._state.get(), - bfr) - if result: - raise ValueError("Error %d while instantiating MD4" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been - hashed so far. - - This method does not change the state of the hash object. - - :Return: A string of 2* `digest_size` characters. It contains only - hexadecimal ASCII digits. - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :Return: A hash object of the same type - """ - - clone = MD4Hash() - result = _raw_md4_lib.md4_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying MD4" % result) - return clone - - def new(self, data=None): - return MD4Hash(data) - - -def new(data=None): - """Return a fresh instance of the hash object. - - :Parameters: - data : byte string/byte array/memoryview - The very first chunk of the message to hash. - It is equivalent to an early call to `MD4Hash.update()`. - Optional. - - :Return: A `MD4Hash` object - """ - return MD4Hash().new(data) - -#: The size of the resulting hash in bytes. -digest_size = MD4Hash.digest_size - -#: The internal block size of the hash algorithm in bytes. -block_size = MD4Hash.block_size diff --git a/Crypto/Hash/MD4.pyi b/Crypto/Hash/MD4.pyi deleted file mode 100644 index a9a7295..0000000 --- a/Crypto/Hash/MD4.pyi +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Union, Optional - -Buffer = Union[bytes, bytearray, memoryview] - -class MD4Hash(object): - digest_size: int - block_size: int - oid: str - - def __init__(self, data: Optional[Buffer] = ...) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> MD4Hash: ... - def new(self, data: Optional[Buffer] = ...) -> MD4Hash: ... - -def new(data: Optional[Buffer] = ...) -> MD4Hash: ... -digest_size: int -block_size: int diff --git a/Crypto/Hash/MD5.py b/Crypto/Hash/MD5.py deleted file mode 100644 index 554b777..0000000 --- a/Crypto/Hash/MD5.py +++ /dev/null @@ -1,184 +0,0 @@ -# -*- coding: utf-8 -*- -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -from Crypto.Util.py3compat import * - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_md5_lib = load_pycryptodome_raw_lib("Crypto.Hash._MD5", - """ - #define MD5_DIGEST_SIZE 16 - - int MD5_init(void **shaState); - int MD5_destroy(void *shaState); - int MD5_update(void *hs, - const uint8_t *buf, - size_t len); - int MD5_digest(const void *shaState, - uint8_t digest[MD5_DIGEST_SIZE]); - int MD5_copy(const void *src, void *dst); - - int MD5_pbkdf2_hmac_assist(const void *inner, - const void *outer, - const uint8_t first_digest[MD5_DIGEST_SIZE], - uint8_t final_digest[MD5_DIGEST_SIZE], - size_t iterations); - """) - -class MD5Hash(object): - """A MD5 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 16 - # The internal block size of the hash algorithm in bytes. - block_size = 64 - # ASN.1 Object ID - oid = "1.2.840.113549.2.5" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_md5_lib.MD5_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating MD5" - % result) - self._state = SmartPointer(state.get(), - _raw_md5_lib.MD5_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_md5_lib.MD5_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while instantiating MD5" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_md5_lib.MD5_digest(self._state.get(), - bfr) - if result: - raise ValueError("Error %d while instantiating MD5" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = MD5Hash() - result = _raw_md5_lib.MD5_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying MD5" % result) - return clone - - def new(self, data=None): - """Create a fresh SHA-1 hash object.""" - - return MD5Hash(data) - - -def new(data=None): - """Create a new hash object. - - :parameter data: - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`MD5Hash.update`. - :type data: byte string/byte array/memoryview - - :Return: A :class:`MD5Hash` hash object - """ - return MD5Hash().new(data) - -# The size of the resulting hash in bytes. -digest_size = 16 - -# The internal block size of the hash algorithm in bytes. -block_size = 64 - - -def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations): - """Compute the expensive inner loop in PBKDF-HMAC.""" - - assert len(first_digest) == digest_size - assert iterations > 0 - - bfr = create_string_buffer(digest_size); - result = _raw_md5_lib.MD5_pbkdf2_hmac_assist( - inner._state.get(), - outer._state.get(), - first_digest, - bfr, - c_size_t(iterations)) - - if result: - raise ValueError("Error %d with PBKDF2-HMAC assis for MD5" % result) - - return get_raw_buffer(bfr) diff --git a/Crypto/Hash/MD5.pyi b/Crypto/Hash/MD5.pyi deleted file mode 100644 index d819556..0000000 --- a/Crypto/Hash/MD5.pyi +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Union - -Buffer = Union[bytes, bytearray, memoryview] - -class MD5Hash(object): - digest_size: int - block_size: int - oid: str - - def __init__(self, data: Buffer = ...) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> MD5Hash: ... - def new(self, data: Buffer = ...) -> MD5Hash: ... - -def new(data: Buffer = ...) -> MD5Hash: ... -digest_size: int -block_size: int diff --git a/Crypto/Hash/Poly1305.py b/Crypto/Hash/Poly1305.py deleted file mode 100644 index eb5e0da..0000000 --- a/Crypto/Hash/Poly1305.py +++ /dev/null @@ -1,217 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Hash/Poly1305.py - Implements the Poly1305 MAC -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -from binascii import unhexlify - -from Crypto.Util.py3compat import bord, tobytes, _copy_bytes - -from Crypto.Hash import BLAKE2s -from Crypto.Random import get_random_bytes -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - - -_raw_poly1305 = load_pycryptodome_raw_lib("Crypto.Hash._poly1305", - """ - int poly1305_init(void **state, - const uint8_t *r, - size_t r_len, - const uint8_t *s, - size_t s_len); - int poly1305_destroy(void *state); - int poly1305_update(void *state, - const uint8_t *in, - size_t len); - int poly1305_digest(const void *state, - uint8_t *digest, - size_t len); - """) - - -class Poly1305_MAC(object): - """An Poly1305 MAC object. - Do not instantiate directly. Use the :func:`new` function. - - :ivar digest_size: the size in bytes of the resulting MAC tag - :vartype digest_size: integer - """ - - digest_size = 16 - - def __init__(self, r, s, data): - - if len(r) != 16: - raise ValueError("Parameter r is not 16 bytes long") - if len(s) != 16: - raise ValueError("Parameter s is not 16 bytes long") - - self._mac_tag = None - - state = VoidPointer() - result = _raw_poly1305.poly1305_init(state.address_of(), - c_uint8_ptr(r), - c_size_t(len(r)), - c_uint8_ptr(s), - c_size_t(len(s)) - ) - if result: - raise ValueError("Error %d while instantiating Poly1305" % result) - self._state = SmartPointer(state.get(), - _raw_poly1305.poly1305_destroy) - if data: - self.update(data) - - def update(self, data): - """Authenticate the next chunk of message. - - Args: - data (byte string/byte array/memoryview): The next chunk of data - """ - - if self._mac_tag: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - - result = _raw_poly1305.poly1305_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while hashing Poly1305 data" % result) - return self - - def copy(self): - raise NotImplementedError() - - def digest(self): - """Return the **binary** (non-printable) MAC tag of the message - authenticated so far. - - :return: The MAC tag digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - if self._mac_tag: - return self._mac_tag - - bfr = create_string_buffer(16) - result = _raw_poly1305.poly1305_digest(self._state.get(), - bfr, - c_size_t(len(bfr))) - if result: - raise ValueError("Error %d while creating Poly1305 digest" % result) - - self._mac_tag = get_raw_buffer(bfr) - return self._mac_tag - - def hexdigest(self): - """Return the **printable** MAC tag of the message authenticated so far. - - :return: The MAC tag, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) - for x in tuple(self.digest())]) - - def verify(self, mac_tag): - """Verify that a given **binary** MAC (computed by another party) - is valid. - - Args: - mac_tag (byte string/byte string/memoryview): the expected MAC of the message. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - secret = get_random_bytes(16) - - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag) - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest()) - - if mac1.digest() != mac2.digest(): - raise ValueError("MAC check failed") - - def hexverify(self, hex_mac_tag): - """Verify that a given **printable** MAC (computed by another party) - is valid. - - Args: - hex_mac_tag (string): the expected MAC of the message, - as a hexadecimal string. - - Raises: - ValueError: if the MAC does not match. It means that the message - has been tampered with or that the MAC key is incorrect. - """ - - self.verify(unhexlify(tobytes(hex_mac_tag))) - - - -def new(**kwargs): - """Create a new Poly1305 MAC object. - - Args: - key (bytes/bytearray/memoryview): - The 32-byte key for the Poly1305 object. - cipher (module from ``Crypto.Cipher``): - The cipher algorithm to use for deriving the Poly1305 - key pair *(r, s)*. - It can only be ``Crypto.Cipher.AES`` or ``Crypto.Cipher.ChaCha20``. - nonce (bytes/bytearray/memoryview): - Optional. The non-repeatable value to use for the MAC of this message. - It must be 16 bytes long for ``AES`` and 8 or 12 bytes for ``ChaCha20``. - If not passed, a random nonce is created; you will find it in the - ``nonce`` attribute of the new object. - data (bytes/bytearray/memoryview): - Optional. The very first chunk of the message to authenticate. - It is equivalent to an early call to ``update()``. - - Returns: - A :class:`Poly1305_MAC` object - """ - - cipher = kwargs.pop("cipher", None) - if not hasattr(cipher, '_derive_Poly1305_key_pair'): - raise ValueError("Parameter 'cipher' must be AES or ChaCha20") - - cipher_key = kwargs.pop("key", None) - if cipher_key is None: - raise TypeError("You must pass a parameter 'key'") - - nonce = kwargs.pop("nonce", None) - data = kwargs.pop("data", None) - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - r, s, nonce = cipher._derive_Poly1305_key_pair(cipher_key, nonce) - - new_mac = Poly1305_MAC(r, s, data) - new_mac.nonce = _copy_bytes(None, None, nonce) # nonce may still be just a memoryview - return new_mac diff --git a/Crypto/Hash/Poly1305.pyi b/Crypto/Hash/Poly1305.pyi deleted file mode 100644 index f97a14a..0000000 --- a/Crypto/Hash/Poly1305.pyi +++ /dev/null @@ -1,24 +0,0 @@ -from types import ModuleType -from typing import Union - -Buffer = Union[bytes, bytearray, memoryview] - -class Poly1305_MAC(object): - block_size: int - digest_size: int - oid: str - - def __init__(self, - r : int, - s : int, - data : Buffer) -> None: ... - def update(self, data: Buffer) -> Poly1305_MAC: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def verify(self, mac_tag: Buffer) -> None: ... - def hexverify(self, hex_mac_tag: str) -> None: ... - -def new(key: Buffer, - cipher: ModuleType, - nonce: Buffer = ..., - data: Buffer = ...) -> Poly1305_MAC: ... diff --git a/Crypto/Hash/RIPEMD.py b/Crypto/Hash/RIPEMD.py deleted file mode 100644 index 4e80235..0000000 --- a/Crypto/Hash/RIPEMD.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -# This file exists for backward compatibility with old code that refers to -# Crypto.Hash.RIPEMD - -"""Deprecated alias for `Crypto.Hash.RIPEMD160`""" - -from Crypto.Hash.RIPEMD160 import new, block_size, digest_size diff --git a/Crypto/Hash/RIPEMD.pyi b/Crypto/Hash/RIPEMD.pyi deleted file mode 100644 index e33eb2d..0000000 --- a/Crypto/Hash/RIPEMD.pyi +++ /dev/null @@ -1,3 +0,0 @@ -# This file exists for backward compatibility with old code that refers to -# Crypto.Hash.SHA - diff --git a/Crypto/Hash/RIPEMD160.py b/Crypto/Hash/RIPEMD160.py deleted file mode 100644 index 820b57d..0000000 --- a/Crypto/Hash/RIPEMD160.py +++ /dev/null @@ -1,169 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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 Crypto.Util.py3compat import bord - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_ripemd160_lib = load_pycryptodome_raw_lib( - "Crypto.Hash._RIPEMD160", - """ - int ripemd160_init(void **shaState); - int ripemd160_destroy(void *shaState); - int ripemd160_update(void *hs, - const uint8_t *buf, - size_t len); - int ripemd160_digest(const void *shaState, - uint8_t digest[20]); - int ripemd160_copy(const void *src, void *dst); - """) - - -class RIPEMD160Hash(object): - """A RIPEMD-160 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 20 - # The internal block size of the hash algorithm in bytes. - block_size = 64 - # ASN.1 Object ID - oid = "1.3.36.3.2.1" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_ripemd160_lib.ripemd160_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating RIPEMD160" - % result) - self._state = SmartPointer(state.get(), - _raw_ripemd160_lib.ripemd160_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_ripemd160_lib.ripemd160_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while instantiating ripemd160" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_ripemd160_lib.ripemd160_digest(self._state.get(), - bfr) - if result: - raise ValueError("Error %d while instantiating ripemd160" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = RIPEMD160Hash() - result = _raw_ripemd160_lib.ripemd160_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying ripemd160" % result) - return clone - - def new(self, data=None): - """Create a fresh RIPEMD-160 hash object.""" - - return RIPEMD160Hash(data) - - -def new(data=None): - """Create a new hash object. - - :parameter data: - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`RIPEMD160Hash.update`. - :type data: byte string/byte array/memoryview - - :Return: A :class:`RIPEMD160Hash` hash object - """ - - return RIPEMD160Hash().new(data) - -# The size of the resulting hash in bytes. -digest_size = RIPEMD160Hash.digest_size - -# The internal block size of the hash algorithm in bytes. -block_size = RIPEMD160Hash.block_size diff --git a/Crypto/Hash/RIPEMD160.pyi b/Crypto/Hash/RIPEMD160.pyi deleted file mode 100644 index b619473..0000000 --- a/Crypto/Hash/RIPEMD160.pyi +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Union - -Buffer = Union[bytes, bytearray, memoryview] - -class RIPEMD160Hash(object): - digest_size: int - block_size: int - oid: str - - def __init__(self, data: Buffer = ...) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> RIPEMD160Hash: ... - def new(self, data: Buffer = ...) -> RIPEMD160Hash: ... - -def new(data: Buffer = ...) -> RIPEMD160Hash: ... -digest_size: int -block_size: int diff --git a/Crypto/Hash/SHA.py b/Crypto/Hash/SHA.py deleted file mode 100644 index 0cc141c..0000000 --- a/Crypto/Hash/SHA.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -# This file exists for backward compatibility with old code that refers to -# Crypto.Hash.SHA - -from Crypto.Hash.SHA1 import __doc__, new, block_size, digest_size diff --git a/Crypto/Hash/SHA.pyi b/Crypto/Hash/SHA.pyi deleted file mode 100644 index 4d7d57e..0000000 --- a/Crypto/Hash/SHA.pyi +++ /dev/null @@ -1,4 +0,0 @@ -# This file exists for backward compatibility with old code that refers to -# Crypto.Hash.SHA - -from Crypto.Hash.SHA1 import __doc__, new, block_size, digest_size diff --git a/Crypto/Hash/SHA1.py b/Crypto/Hash/SHA1.py deleted file mode 100644 index f79d825..0000000 --- a/Crypto/Hash/SHA1.py +++ /dev/null @@ -1,185 +0,0 @@ -# -*- coding: utf-8 -*- -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -from Crypto.Util.py3compat import * - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_sha1_lib = load_pycryptodome_raw_lib("Crypto.Hash._SHA1", - """ - #define SHA1_DIGEST_SIZE 20 - - int SHA1_init(void **shaState); - int SHA1_destroy(void *shaState); - int SHA1_update(void *hs, - const uint8_t *buf, - size_t len); - int SHA1_digest(const void *shaState, - uint8_t digest[SHA1_DIGEST_SIZE]); - int SHA1_copy(const void *src, void *dst); - - int SHA1_pbkdf2_hmac_assist(const void *inner, - const void *outer, - const uint8_t first_digest[SHA1_DIGEST_SIZE], - uint8_t final_digest[SHA1_DIGEST_SIZE], - size_t iterations); - """) - -class SHA1Hash(object): - """A SHA-1 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 20 - # The internal block size of the hash algorithm in bytes. - block_size = 64 - # ASN.1 Object ID - oid = "1.3.14.3.2.26" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_sha1_lib.SHA1_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating SHA1" - % result) - self._state = SmartPointer(state.get(), - _raw_sha1_lib.SHA1_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_sha1_lib.SHA1_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while instantiating SHA1" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_sha1_lib.SHA1_digest(self._state.get(), - bfr) - if result: - raise ValueError("Error %d while instantiating SHA1" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = SHA1Hash() - result = _raw_sha1_lib.SHA1_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHA1" % result) - return clone - - def new(self, data=None): - """Create a fresh SHA-1 hash object.""" - - return SHA1Hash(data) - - -def new(data=None): - """Create a new hash object. - - :parameter data: - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`SHA1Hash.update`. - :type data: byte string/byte array/memoryview - - :Return: A :class:`SHA1Hash` hash object - """ - return SHA1Hash().new(data) - - -# The size of the resulting hash in bytes. -digest_size = SHA1Hash.digest_size - -# The internal block size of the hash algorithm in bytes. -block_size = SHA1Hash.block_size - - -def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations): - """Compute the expensive inner loop in PBKDF-HMAC.""" - - assert len(first_digest) == digest_size - assert iterations > 0 - - bfr = create_string_buffer(digest_size); - result = _raw_sha1_lib.SHA1_pbkdf2_hmac_assist( - inner._state.get(), - outer._state.get(), - first_digest, - bfr, - c_size_t(iterations)) - - if result: - raise ValueError("Error %d with PBKDF2-HMAC assis for SHA1" % result) - - return get_raw_buffer(bfr) diff --git a/Crypto/Hash/SHA1.pyi b/Crypto/Hash/SHA1.pyi deleted file mode 100644 index d6c8e25..0000000 --- a/Crypto/Hash/SHA1.pyi +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Union, Optional - -Buffer = Union[bytes, bytearray, memoryview] - -class SHA1Hash(object): - digest_size: int - block_size: int - oid: str - - def __init__(self, data: Optional[Buffer] = ...) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> SHA1Hash: ... - def new(self, data: Optional[Buffer] = ...) -> SHA1Hash: ... - -def new(data: Optional[Buffer] = ...) -> SHA1Hash: ... -digest_size: int -block_size: int diff --git a/Crypto/Hash/SHA224.py b/Crypto/Hash/SHA224.py deleted file mode 100644 index f788b06..0000000 --- a/Crypto/Hash/SHA224.py +++ /dev/null @@ -1,186 +0,0 @@ -# -*- coding: utf-8 -*- -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -from Crypto.Util.py3compat import bord - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_sha224_lib = load_pycryptodome_raw_lib("Crypto.Hash._SHA224", - """ - int SHA224_init(void **shaState); - int SHA224_destroy(void *shaState); - int SHA224_update(void *hs, - const uint8_t *buf, - size_t len); - int SHA224_digest(const void *shaState, - uint8_t *digest, - size_t digest_size); - int SHA224_copy(const void *src, void *dst); - - int SHA224_pbkdf2_hmac_assist(const void *inner, - const void *outer, - const uint8_t *first_digest, - uint8_t *final_digest, - size_t iterations, - size_t digest_size); - """) - -class SHA224Hash(object): - """A SHA-224 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 28 - # The internal block size of the hash algorithm in bytes. - block_size = 64 - # ASN.1 Object ID - oid = '2.16.840.1.101.3.4.2.4' - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_sha224_lib.SHA224_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating SHA224" - % result) - self._state = SmartPointer(state.get(), - _raw_sha224_lib.SHA224_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_sha224_lib.SHA224_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while hashing data with SHA224" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_sha224_lib.SHA224_digest(self._state.get(), - bfr, - c_size_t(self.digest_size)) - if result: - raise ValueError("Error %d while making SHA224 digest" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = SHA224Hash() - result = _raw_sha224_lib.SHA224_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHA224" % result) - return clone - - def new(self, data=None): - """Create a fresh SHA-224 hash object.""" - - return SHA224Hash(data) - - -def new(data=None): - """Create a new hash object. - - :parameter data: - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`SHA224Hash.update`. - :type data: byte string/byte array/memoryview - - :Return: A :class:`SHA224Hash` hash object - """ - return SHA224Hash().new(data) - - -# The size of the resulting hash in bytes. -digest_size = SHA224Hash.digest_size - -# The internal block size of the hash algorithm in bytes. -block_size = SHA224Hash.block_size - - -def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations): - """Compute the expensive inner loop in PBKDF-HMAC.""" - - assert iterations > 0 - - bfr = create_string_buffer(len(first_digest)); - result = _raw_sha224_lib.SHA224_pbkdf2_hmac_assist( - inner._state.get(), - outer._state.get(), - first_digest, - bfr, - c_size_t(iterations), - c_size_t(len(first_digest))) - - if result: - raise ValueError("Error %d with PBKDF2-HMAC assist for SHA224" % result) - - return get_raw_buffer(bfr) diff --git a/Crypto/Hash/SHA224.pyi b/Crypto/Hash/SHA224.pyi deleted file mode 100644 index 613a7f9..0000000 --- a/Crypto/Hash/SHA224.pyi +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Union, Optional - -Buffer = Union[bytes, bytearray, memoryview] - -class SHA224Hash(object): - digest_size: int - block_size: int - oid: str - - def __init__(self, data: Optional[Buffer] = ...) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> SHA224Hash: ... - def new(self, data: Optional[Buffer] = ...) -> SHA224Hash: ... - -def new(data: Optional[Buffer] = ...) -> SHA224Hash: ... -digest_size: int -block_size: int diff --git a/Crypto/Hash/SHA256.py b/Crypto/Hash/SHA256.py deleted file mode 100644 index 957aa37..0000000 --- a/Crypto/Hash/SHA256.py +++ /dev/null @@ -1,185 +0,0 @@ -# -*- coding: utf-8 -*- -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -from Crypto.Util.py3compat import bord - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_sha256_lib = load_pycryptodome_raw_lib("Crypto.Hash._SHA256", - """ - int SHA256_init(void **shaState); - int SHA256_destroy(void *shaState); - int SHA256_update(void *hs, - const uint8_t *buf, - size_t len); - int SHA256_digest(const void *shaState, - uint8_t *digest, - size_t digest_size); - int SHA256_copy(const void *src, void *dst); - - int SHA256_pbkdf2_hmac_assist(const void *inner, - const void *outer, - const uint8_t *first_digest, - uint8_t *final_digest, - size_t iterations, - size_t digest_size); - """) - -class SHA256Hash(object): - """A SHA-256 hash object. - Do not instantiate directly. Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 32 - # The internal block size of the hash algorithm in bytes. - block_size = 64 - # ASN.1 Object ID - oid = "2.16.840.1.101.3.4.2.1" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_sha256_lib.SHA256_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating SHA256" - % result) - self._state = SmartPointer(state.get(), - _raw_sha256_lib.SHA256_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_sha256_lib.SHA256_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while hashing data with SHA256" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_sha256_lib.SHA256_digest(self._state.get(), - bfr, - c_size_t(self.digest_size)) - if result: - raise ValueError("Error %d while making SHA256 digest" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = SHA256Hash() - result = _raw_sha256_lib.SHA256_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHA256" % result) - return clone - - def new(self, data=None): - """Create a fresh SHA-256 hash object.""" - - return SHA256Hash(data) - -def new(data=None): - """Create a new hash object. - - :parameter data: - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`SHA256Hash.update`. - :type data: byte string/byte array/memoryview - - :Return: A :class:`SHA256Hash` hash object - """ - - return SHA256Hash().new(data) - - -# The size of the resulting hash in bytes. -digest_size = SHA256Hash.digest_size - -# The internal block size of the hash algorithm in bytes. -block_size = SHA256Hash.block_size - - -def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations): - """Compute the expensive inner loop in PBKDF-HMAC.""" - - assert iterations > 0 - - bfr = create_string_buffer(len(first_digest)); - result = _raw_sha256_lib.SHA256_pbkdf2_hmac_assist( - inner._state.get(), - outer._state.get(), - first_digest, - bfr, - c_size_t(iterations), - c_size_t(len(first_digest))) - - if result: - raise ValueError("Error %d with PBKDF2-HMAC assist for SHA256" % result) - - return get_raw_buffer(bfr) diff --git a/Crypto/Hash/SHA256.pyi b/Crypto/Hash/SHA256.pyi deleted file mode 100644 index cbf21bf..0000000 --- a/Crypto/Hash/SHA256.pyi +++ /dev/null @@ -1,18 +0,0 @@ -from typing import Union, Optional - - -class SHA256Hash(object): - digest_size: int - block_size: int - oid: str - def __init__(self, data: Optional[Union[bytes, bytearray, memoryview]]=None) -> None: ... - def update(self, data: Union[bytes, bytearray, memoryview]) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> SHA256Hash: ... - def new(self, data: Optional[Union[bytes, bytearray, memoryview]]=None) -> SHA256Hash: ... - -def new(data: Optional[Union[bytes, bytearray, memoryview]]=None) -> SHA256Hash: ... - -digest_size: int -block_size: int diff --git a/Crypto/Hash/SHA384.py b/Crypto/Hash/SHA384.py deleted file mode 100644 index a98fa9a..0000000 --- a/Crypto/Hash/SHA384.py +++ /dev/null @@ -1,186 +0,0 @@ -# -*- coding: utf-8 -*- -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -from Crypto.Util.py3compat import bord - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_sha384_lib = load_pycryptodome_raw_lib("Crypto.Hash._SHA384", - """ - int SHA384_init(void **shaState); - int SHA384_destroy(void *shaState); - int SHA384_update(void *hs, - const uint8_t *buf, - size_t len); - int SHA384_digest(const void *shaState, - uint8_t *digest, - size_t digest_size); - int SHA384_copy(const void *src, void *dst); - - int SHA384_pbkdf2_hmac_assist(const void *inner, - const void *outer, - const uint8_t *first_digest, - uint8_t *final_digest, - size_t iterations, - size_t digest_size); - """) - -class SHA384Hash(object): - """A SHA-384 hash object. - Do not instantiate directly. Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 48 - # The internal block size of the hash algorithm in bytes. - block_size = 128 - # ASN.1 Object ID - oid = '2.16.840.1.101.3.4.2.2' - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_sha384_lib.SHA384_init(state.address_of()) - if result: - raise ValueError("Error %d while instantiating SHA384" - % result) - self._state = SmartPointer(state.get(), - _raw_sha384_lib.SHA384_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_sha384_lib.SHA384_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while hashing data with SHA384" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_sha384_lib.SHA384_digest(self._state.get(), - bfr, - c_size_t(self.digest_size)) - if result: - raise ValueError("Error %d while making SHA384 digest" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = SHA384Hash() - result = _raw_sha384_lib.SHA384_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHA384" % result) - return clone - - def new(self, data=None): - """Create a fresh SHA-384 hash object.""" - - return SHA384Hash(data) - - -def new(data=None): - """Create a new hash object. - - :parameter data: - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`SHA384Hash.update`. - :type data: byte string/byte array/memoryview - - :Return: A :class:`SHA384Hash` hash object - """ - - return SHA384Hash().new(data) - - -# The size of the resulting hash in bytes. -digest_size = SHA384Hash.digest_size - -# The internal block size of the hash algorithm in bytes. -block_size = SHA384Hash.block_size - - -def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations): - """Compute the expensive inner loop in PBKDF-HMAC.""" - - assert iterations > 0 - - bfr = create_string_buffer(len(first_digest)); - result = _raw_sha384_lib.SHA384_pbkdf2_hmac_assist( - inner._state.get(), - outer._state.get(), - first_digest, - bfr, - c_size_t(iterations), - c_size_t(len(first_digest))) - - if result: - raise ValueError("Error %d with PBKDF2-HMAC assist for SHA384" % result) - - return get_raw_buffer(bfr) diff --git a/Crypto/Hash/SHA384.pyi b/Crypto/Hash/SHA384.pyi deleted file mode 100644 index c2aab9e..0000000 --- a/Crypto/Hash/SHA384.pyi +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Union, Optional - -Buffer = Union[bytes, bytearray, memoryview] - -class SHA384Hash(object): - digest_size: int - block_size: int - oid: str - - def __init__(self, data: Optional[Buffer] = ...) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> SHA384Hash: ... - def new(self, data: Optional[Buffer] = ...) -> SHA384Hash: ... - -def new(data: Optional[Buffer] = ...) -> SHA384Hash: ... -digest_size: int -block_size: int diff --git a/Crypto/Hash/SHA3_224.py b/Crypto/Hash/SHA3_224.py deleted file mode 100644 index bfc9bc2..0000000 --- a/Crypto/Hash/SHA3_224.py +++ /dev/null @@ -1,147 +0,0 @@ -# -*- coding: utf-8 -*- -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -from Crypto.Util.py3compat import bord - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -from Crypto.Hash.keccak import _raw_keccak_lib - -class SHA3_224_Hash(object): - """A SHA3-224 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 28 - - # ASN.1 Object ID - oid = "2.16.840.1.101.3.4.2.7" - - def __init__(self, data, update_after_digest): - self._update_after_digest = update_after_digest - self._digest_done = False - - state = VoidPointer() - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(self.digest_size * 2), - 0x06) - if result: - raise ValueError("Error %d while instantiating SHA-3/224" - % result) - self._state = SmartPointer(state.get(), - _raw_keccak_lib.keccak_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._digest_done and not self._update_after_digest: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while updating SHA-3/224" - % result) - return self - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - self._digest_done = True - - bfr = create_string_buffer(self.digest_size) - result = _raw_keccak_lib.keccak_digest(self._state.get(), - bfr, - c_size_t(self.digest_size)) - if result: - raise ValueError("Error %d while instantiating SHA-3/224" - % result) - - self._digest_value = get_raw_buffer(bfr) - return self._digest_value - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def new(self): - """Create a fresh SHA3-224 hash object.""" - - return type(self)(None, self._update_after_digest) - - -def new(*args, **kwargs): - """Create a new hash object. - - Args: - data (byte string/byte array/memoryview): - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - update_after_digest (boolean): - Whether :meth:`digest` can be followed by another :meth:`update` - (default: ``False``). - - :Return: A :class:`SHA3_224_Hash` hash object - """ - - data = kwargs.pop("data", None) - update_after_digest = kwargs.pop("update_after_digest", False) - if len(args) == 1: - if data: - raise ValueError("Initial data for hash specified twice") - data = args[0] - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return SHA3_224_Hash(data, update_after_digest) - -# The size of the resulting hash in bytes. -digest_size = SHA3_224_Hash.digest_size diff --git a/Crypto/Hash/SHA3_224.pyi b/Crypto/Hash/SHA3_224.pyi deleted file mode 100644 index 3437042..0000000 --- a/Crypto/Hash/SHA3_224.pyi +++ /dev/null @@ -1,16 +0,0 @@ -from typing import Union, Optional - -Buffer = Union[bytes, bytearray, memoryview] - -class SHA3_224_Hash(object): - digest_size: int - oid: str - def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> SHA3_224_Hash: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def new(self) -> SHA3_224_Hash: ... - -def new(__data: Buffer = ..., update_after_digest: bool = ...) -> SHA3_224_Hash: ... - -digest_size: int diff --git a/Crypto/Hash/SHA3_256.py b/Crypto/Hash/SHA3_256.py deleted file mode 100644 index 327dabf..0000000 --- a/Crypto/Hash/SHA3_256.py +++ /dev/null @@ -1,147 +0,0 @@ -# -*- coding: utf-8 -*- -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -from Crypto.Util.py3compat import bord - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -from Crypto.Hash.keccak import _raw_keccak_lib - -class SHA3_256_Hash(object): - """A SHA3-256 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 32 - - # ASN.1 Object ID - oid = "2.16.840.1.101.3.4.2.8" - - def __init__(self, data, update_after_digest): - self._update_after_digest = update_after_digest - self._digest_done = False - - state = VoidPointer() - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(self.digest_size * 2), - 0x06) - if result: - raise ValueError("Error %d while instantiating SHA-3/256" - % result) - self._state = SmartPointer(state.get(), - _raw_keccak_lib.keccak_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._digest_done and not self._update_after_digest: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while updating SHA-3/256" - % result) - return self - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - self._digest_done = True - - bfr = create_string_buffer(self.digest_size) - result = _raw_keccak_lib.keccak_digest(self._state.get(), - bfr, - c_size_t(self.digest_size)) - if result: - raise ValueError("Error %d while instantiating SHA-3/256" - % result) - - self._digest_value = get_raw_buffer(bfr) - return self._digest_value - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def new(self): - """Create a fresh SHA3-256 hash object.""" - - return type(self)(None, self._update_after_digest) - - -def new(*args, **kwargs): - """Create a new hash object. - - Args: - data (byte string/byte array/memoryview): - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - update_after_digest (boolean): - Whether :meth:`digest` can be followed by another :meth:`update` - (default: ``False``). - - :Return: A :class:`SHA3_256_Hash` hash object - """ - - data = kwargs.pop("data", None) - update_after_digest = kwargs.pop("update_after_digest", False) - if len(args) == 1: - if data: - raise ValueError("Initial data for hash specified twice") - data = args[0] - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return SHA3_256_Hash(data, update_after_digest) - -# The size of the resulting hash in bytes. -digest_size = SHA3_256_Hash.digest_size diff --git a/Crypto/Hash/SHA3_256.pyi b/Crypto/Hash/SHA3_256.pyi deleted file mode 100644 index c1a07fa..0000000 --- a/Crypto/Hash/SHA3_256.pyi +++ /dev/null @@ -1,16 +0,0 @@ -from typing import Union, Optional - -Buffer = Union[bytes, bytearray, memoryview] - -class SHA3_256_Hash(object): - digest_size: int - oid: str - def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> SHA3_256_Hash: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def new(self) -> SHA3_256_Hash: ... - -def new(__data: Buffer = ..., update_after_digest: bool = ...) -> SHA3_256_Hash: ... - -digest_size: int diff --git a/Crypto/Hash/SHA3_384.py b/Crypto/Hash/SHA3_384.py deleted file mode 100644 index cdbb7dd..0000000 --- a/Crypto/Hash/SHA3_384.py +++ /dev/null @@ -1,147 +0,0 @@ -# -*- coding: utf-8 -*- -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -from Crypto.Util.py3compat import bord - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -from Crypto.Hash.keccak import _raw_keccak_lib - -class SHA3_384_Hash(object): - """A SHA3-384 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 48 - - # ASN.1 Object ID - oid = "2.16.840.1.101.3.4.2.9" - - def __init__(self, data, update_after_digest): - self._update_after_digest = update_after_digest - self._digest_done = False - - state = VoidPointer() - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(self.digest_size * 2), - 0x06) - if result: - raise ValueError("Error %d while instantiating SHA-3/384" - % result) - self._state = SmartPointer(state.get(), - _raw_keccak_lib.keccak_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._digest_done and not self._update_after_digest: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while updating SHA-3/384" - % result) - return self - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - self._digest_done = True - - bfr = create_string_buffer(self.digest_size) - result = _raw_keccak_lib.keccak_digest(self._state.get(), - bfr, - c_size_t(self.digest_size)) - if result: - raise ValueError("Error %d while instantiating SHA-3/384" - % result) - - self._digest_value = get_raw_buffer(bfr) - return self._digest_value - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def new(self): - """Create a fresh SHA3-384 hash object.""" - - return type(self)(None, self._update_after_digest) - - -def new(*args, **kwargs): - """Create a new hash object. - - Args: - data (byte string/byte array/memoryview): - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - update_after_digest (boolean): - Whether :meth:`digest` can be followed by another :meth:`update` - (default: ``False``). - - :Return: A :class:`SHA3_384_Hash` hash object - """ - - data = kwargs.pop("data", None) - update_after_digest = kwargs.pop("update_after_digest", False) - if len(args) == 1: - if data: - raise ValueError("Initial data for hash specified twice") - data = args[0] - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return SHA3_384_Hash(data, update_after_digest) - -# The size of the resulting hash in bytes. -digest_size = SHA3_384_Hash.digest_size diff --git a/Crypto/Hash/SHA3_384.pyi b/Crypto/Hash/SHA3_384.pyi deleted file mode 100644 index d029ab6..0000000 --- a/Crypto/Hash/SHA3_384.pyi +++ /dev/null @@ -1,16 +0,0 @@ -from typing import Union, Optional - -Buffer = Union[bytes, bytearray, memoryview] - -class SHA3_384_Hash(object): - digest_size: int - oid: str - def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> SHA3_384_Hash: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def new(self) -> SHA3_384_Hash: ... - -def new(__data: Buffer = ..., update_after_digest: bool = ...) -> SHA3_384_Hash: ... - -digest_size: int diff --git a/Crypto/Hash/SHA3_512.py b/Crypto/Hash/SHA3_512.py deleted file mode 100644 index 355b049..0000000 --- a/Crypto/Hash/SHA3_512.py +++ /dev/null @@ -1,148 +0,0 @@ -# -*- coding: utf-8 -*- -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -from Crypto.Util.py3compat import bord - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -from Crypto.Hash.keccak import _raw_keccak_lib - -class SHA3_512_Hash(object): - """A SHA3-512 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The size of the resulting hash in bytes. - digest_size = 64 - - # ASN.1 Object ID - oid = "2.16.840.1.101.3.4.2.10" - - def __init__(self, data, update_after_digest): - self._update_after_digest = update_after_digest - self._digest_done = False - - state = VoidPointer() - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(self.digest_size * 2), - 0x06) - if result: - raise ValueError("Error %d while instantiating SHA-3/512" - % result) - self._state = SmartPointer(state.get(), - _raw_keccak_lib.keccak_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._digest_done and not self._update_after_digest: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while updating SHA-3/512" - % result) - return self - - def digest(self): - - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - self._digest_done = True - - bfr = create_string_buffer(self.digest_size) - result = _raw_keccak_lib.keccak_digest(self._state.get(), - bfr, - c_size_t(self.digest_size)) - if result: - raise ValueError("Error %d while instantiating SHA-3/512" - % result) - - self._digest_value = get_raw_buffer(bfr) - return self._digest_value - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def new(self): - """Create a fresh SHA3-512 hash object.""" - - return type(self)(None, self._update_after_digest) - - -def new(*args, **kwargs): - """Create a new hash object. - - Args: - data (byte string/byte array/memoryview): - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - update_after_digest (boolean): - Whether :meth:`digest` can be followed by another :meth:`update` - (default: ``False``). - - :Return: A :class:`SHA3_512_Hash` hash object - """ - - data = kwargs.pop("data", None) - update_after_digest = kwargs.pop("update_after_digest", False) - if len(args) == 1: - if data: - raise ValueError("Initial data for hash specified twice") - data = args[0] - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return SHA3_512_Hash(data, update_after_digest) - -# The size of the resulting hash in bytes. -digest_size = SHA3_512_Hash.digest_size diff --git a/Crypto/Hash/SHA3_512.pyi b/Crypto/Hash/SHA3_512.pyi deleted file mode 100644 index 2c5403b..0000000 --- a/Crypto/Hash/SHA3_512.pyi +++ /dev/null @@ -1,16 +0,0 @@ -from typing import Union, Optional - -Buffer = Union[bytes, bytearray, memoryview] - -class SHA3_512_Hash(object): - digest_size: int - oid: str - def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> SHA3_512_Hash: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def new(self) -> SHA3_512_Hash: ... - -def new(__data: Buffer = ..., update_after_digest: bool = ...) -> SHA3_512_Hash: ... - -digest_size: int diff --git a/Crypto/Hash/SHA512.py b/Crypto/Hash/SHA512.py deleted file mode 100644 index 403fe45..0000000 --- a/Crypto/Hash/SHA512.py +++ /dev/null @@ -1,204 +0,0 @@ -# -*- coding: utf-8 -*- -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -from Crypto.Util.py3compat import bord - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_sha512_lib = load_pycryptodome_raw_lib("Crypto.Hash._SHA512", - """ - int SHA512_init(void **shaState, - size_t digest_size); - int SHA512_destroy(void *shaState); - int SHA512_update(void *hs, - const uint8_t *buf, - size_t len); - int SHA512_digest(const void *shaState, - uint8_t *digest, - size_t digest_size); - int SHA512_copy(const void *src, void *dst); - - int SHA512_pbkdf2_hmac_assist(const void *inner, - const void *outer, - const uint8_t *first_digest, - uint8_t *final_digest, - size_t iterations, - size_t digest_size); - """) - -class SHA512Hash(object): - """A SHA-512 hash object (possibly in its truncated version SHA-512/224 or - SHA-512/256. - Do not instantiate directly. Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - - :ivar block_size: the size in bytes of the internal message block, - input to the compression function - :vartype block_size: integer - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - # The internal block size of the hash algorithm in bytes. - block_size = 128 - - def __init__(self, data, truncate): - self._truncate = truncate - - if truncate is None: - self.oid = "2.16.840.1.101.3.4.2.3" - self.digest_size = 64 - elif truncate == "224": - self.oid = "2.16.840.1.101.3.4.2.5" - self.digest_size = 28 - elif truncate == "256": - self.oid = "2.16.840.1.101.3.4.2.6" - self.digest_size = 32 - else: - raise ValueError("Incorrect truncation length. It must be '224' or '256'.") - - state = VoidPointer() - result = _raw_sha512_lib.SHA512_init(state.address_of(), - c_size_t(self.digest_size)) - if result: - raise ValueError("Error %d while instantiating SHA-512" - % result) - self._state = SmartPointer(state.get(), - _raw_sha512_lib.SHA512_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - result = _raw_sha512_lib.SHA512_update(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while hashing data with SHA512" - % result) - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - bfr = create_string_buffer(self.digest_size) - result = _raw_sha512_lib.SHA512_digest(self._state.get(), - bfr, - c_size_t(self.digest_size)) - if result: - raise ValueError("Error %d while making SHA512 digest" - % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def copy(self): - """Return a copy ("clone") of the hash object. - - The copy will have the same internal state as the original hash - object. - This can be used to efficiently compute the digests of strings that - share a common initial substring. - - :return: A hash object of the same type - """ - - clone = SHA512Hash(None, self._truncate) - result = _raw_sha512_lib.SHA512_copy(self._state.get(), - clone._state.get()) - if result: - raise ValueError("Error %d while copying SHA512" % result) - return clone - - def new(self, data=None): - """Create a fresh SHA-512 hash object.""" - - return SHA512Hash(data, self._truncate) - - -def new(data=None, truncate=None): - """Create a new hash object. - - Args: - data (bytes/bytearray/memoryview): - Optional. The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`SHA512Hash.update`. - truncate (string): - Optional. The desired length of the digest. It can be either "224" or - "256". If not present, the digest is 512 bits long. - Passing this parameter is **not** equivalent to simply truncating - the output digest. - - :Return: A :class:`SHA512Hash` hash object - """ - - return SHA512Hash(data, truncate) - - -# The size of the full SHA-512 hash in bytes. -digest_size = 64 - -# The internal block size of the hash algorithm in bytes. -block_size = 128 - - -def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations): - """Compute the expensive inner loop in PBKDF-HMAC.""" - - assert iterations > 0 - - bfr = create_string_buffer(len(first_digest)); - result = _raw_sha512_lib.SHA512_pbkdf2_hmac_assist( - inner._state.get(), - outer._state.get(), - first_digest, - bfr, - c_size_t(iterations), - c_size_t(len(first_digest))) - - if result: - raise ValueError("Error %d with PBKDF2-HMAC assist for SHA512" % result) - - return get_raw_buffer(bfr) diff --git a/Crypto/Hash/SHA512.pyi b/Crypto/Hash/SHA512.pyi deleted file mode 100644 index f219ee9..0000000 --- a/Crypto/Hash/SHA512.pyi +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Union, Optional - -Buffer = Union[bytes, bytearray, memoryview] - -class SHA512Hash(object): - digest_size: int - block_size: int - oid: str - - def __init__(self, - data: Optional[Buffer], - truncate: Optional[str]) -> None: ... - def update(self, data: Buffer) -> None: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def copy(self) -> SHA512Hash: ... - def new(self, data: Optional[Buffer] = ...) -> SHA512Hash: ... - -def new(data: Optional[Buffer] = ..., - truncate: Optional[str] = ...) -> SHA512Hash: ... -digest_size: int -block_size: int diff --git a/Crypto/Hash/SHAKE128.py b/Crypto/Hash/SHAKE128.py deleted file mode 100644 index 011268b..0000000 --- a/Crypto/Hash/SHAKE128.py +++ /dev/null @@ -1,127 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2015, Legrandin -# 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 Crypto.Util.py3compat import bord - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -from Crypto.Hash.keccak import _raw_keccak_lib - -class SHAKE128_XOF(object): - """A SHAKE128 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - """ - - # ASN.1 Object ID - oid = "2.16.840.1.101.3.4.2.11" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(32), - 0x1F) - if result: - raise ValueError("Error %d while instantiating SHAKE128" - % result) - self._state = SmartPointer(state.get(), - _raw_keccak_lib.keccak_destroy) - self._is_squeezing = False - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._is_squeezing: - raise TypeError("You cannot call 'update' after the first 'read'") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while updating SHAKE128 state" - % result) - return self - - def read(self, length): - """ - Compute the next piece of XOF output. - - .. note:: - You cannot use :meth:`update` anymore after the first call to - :meth:`read`. - - Args: - length (integer): the amount of bytes this method must return - - :return: the next piece of XOF output (of the given length) - :rtype: byte string - """ - - self._is_squeezing = True - bfr = create_string_buffer(length) - result = _raw_keccak_lib.keccak_squeeze(self._state.get(), - bfr, - c_size_t(length)) - if result: - raise ValueError("Error %d while extracting from SHAKE128" - % result) - - return get_raw_buffer(bfr) - - def new(self, data=None): - return type(self)(data=data) - - -def new(data=None): - """Return a fresh instance of a SHAKE128 object. - - Args: - data (bytes/bytearray/memoryview): - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - Optional. - - :Return: A :class:`SHAKE128_XOF` object - """ - - return SHAKE128_XOF(data=data) diff --git a/Crypto/Hash/SHAKE128.pyi b/Crypto/Hash/SHAKE128.pyi deleted file mode 100644 index f618881..0000000 --- a/Crypto/Hash/SHAKE128.pyi +++ /dev/null @@ -1,13 +0,0 @@ -from typing import Union, Optional - -Buffer = Union[bytes, bytearray, memoryview] - -class SHAKE128_XOF(object): - oid: str - def __init__(self, - data: Optional[Buffer] = ...) -> None: ... - def update(self, data: Buffer) -> SHAKE128_XOF: ... - def read(self, length: int) -> bytes: ... - def new(self, data: Optional[Buffer] = ...) -> SHAKE128_XOF: ... - -def new(data: Optional[Buffer] = ...) -> SHAKE128_XOF: ... diff --git a/Crypto/Hash/SHAKE256.py b/Crypto/Hash/SHAKE256.py deleted file mode 100644 index 4b1b141..0000000 --- a/Crypto/Hash/SHAKE256.py +++ /dev/null @@ -1,127 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2015, Legrandin -# 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 Crypto.Util.py3compat import bord - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -from Crypto.Hash.keccak import _raw_keccak_lib - -class SHAKE256_XOF(object): - """A SHAKE256 hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar oid: ASN.1 Object ID - :vartype oid: string - """ - - # ASN.1 Object ID - oid = "2.16.840.1.101.3.4.2.12" - - def __init__(self, data=None): - state = VoidPointer() - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(64), - 0x1F) - if result: - raise ValueError("Error %d while instantiating SHAKE256" - % result) - self._state = SmartPointer(state.get(), - _raw_keccak_lib.keccak_destroy) - self._is_squeezing = False - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._is_squeezing: - raise TypeError("You cannot call 'update' after the first 'read'") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while updating SHAKE256 state" - % result) - return self - - def read(self, length): - """ - Compute the next piece of XOF output. - - .. note:: - You cannot use :meth:`update` anymore after the first call to - :meth:`read`. - - Args: - length (integer): the amount of bytes this method must return - - :return: the next piece of XOF output (of the given length) - :rtype: byte string - """ - - self._is_squeezing = True - bfr = create_string_buffer(length) - result = _raw_keccak_lib.keccak_squeeze(self._state.get(), - bfr, - c_size_t(length)) - if result: - raise ValueError("Error %d while extracting from SHAKE256" - % result) - - return get_raw_buffer(bfr) - - def new(self, data=None): - return type(self)(data=data) - - -def new(data=None): - """Return a fresh instance of a SHAKE256 object. - - Args: - data (bytes/bytearray/memoryview): - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`update`. - Optional. - - :Return: A :class:`SHAKE256_XOF` object - """ - - return SHAKE256_XOF(data=data) diff --git a/Crypto/Hash/SHAKE256.pyi b/Crypto/Hash/SHAKE256.pyi deleted file mode 100644 index 029347a..0000000 --- a/Crypto/Hash/SHAKE256.pyi +++ /dev/null @@ -1,13 +0,0 @@ -from typing import Union, Optional - -Buffer = Union[bytes, bytearray, memoryview] - -class SHAKE256_XOF(object): - oid: str - def __init__(self, - data: Optional[Buffer] = ...) -> None: ... - def update(self, data: Buffer) -> SHAKE256_XOF: ... - def read(self, length: int) -> bytes: ... - def new(self, data: Optional[Buffer] = ...) -> SHAKE256_XOF: ... - -def new(data: Optional[Buffer] = ...) -> SHAKE256_XOF: ... diff --git a/Crypto/Hash/_BLAKE2b.abi3.so b/Crypto/Hash/_BLAKE2b.abi3.so deleted file mode 100644 index e2c472f..0000000 Binary files a/Crypto/Hash/_BLAKE2b.abi3.so and /dev/null differ diff --git a/Crypto/Hash/_BLAKE2s.abi3.so b/Crypto/Hash/_BLAKE2s.abi3.so deleted file mode 100644 index d078686..0000000 Binary files a/Crypto/Hash/_BLAKE2s.abi3.so and /dev/null differ diff --git a/Crypto/Hash/_MD2.abi3.so b/Crypto/Hash/_MD2.abi3.so deleted file mode 100644 index 0fde69f..0000000 Binary files a/Crypto/Hash/_MD2.abi3.so and /dev/null differ diff --git a/Crypto/Hash/_MD4.abi3.so b/Crypto/Hash/_MD4.abi3.so deleted file mode 100644 index c783791..0000000 Binary files a/Crypto/Hash/_MD4.abi3.so and /dev/null differ diff --git a/Crypto/Hash/_MD5.abi3.so b/Crypto/Hash/_MD5.abi3.so deleted file mode 100644 index 924b5c5..0000000 Binary files a/Crypto/Hash/_MD5.abi3.so and /dev/null differ diff --git a/Crypto/Hash/_RIPEMD160.abi3.so b/Crypto/Hash/_RIPEMD160.abi3.so deleted file mode 100644 index fbca9c8..0000000 Binary files a/Crypto/Hash/_RIPEMD160.abi3.so and /dev/null differ diff --git a/Crypto/Hash/_SHA1.abi3.so b/Crypto/Hash/_SHA1.abi3.so deleted file mode 100644 index 9f4a015..0000000 Binary files a/Crypto/Hash/_SHA1.abi3.so and /dev/null differ diff --git a/Crypto/Hash/_SHA224.abi3.so b/Crypto/Hash/_SHA224.abi3.so deleted file mode 100644 index dc4dbfb..0000000 Binary files a/Crypto/Hash/_SHA224.abi3.so and /dev/null differ diff --git a/Crypto/Hash/_SHA256.abi3.so b/Crypto/Hash/_SHA256.abi3.so deleted file mode 100644 index 6daaa16..0000000 Binary files a/Crypto/Hash/_SHA256.abi3.so and /dev/null differ diff --git a/Crypto/Hash/_SHA384.abi3.so b/Crypto/Hash/_SHA384.abi3.so deleted file mode 100644 index 7c9a175..0000000 Binary files a/Crypto/Hash/_SHA384.abi3.so and /dev/null differ diff --git a/Crypto/Hash/_SHA512.abi3.so b/Crypto/Hash/_SHA512.abi3.so deleted file mode 100644 index d848ff8..0000000 Binary files a/Crypto/Hash/_SHA512.abi3.so and /dev/null differ diff --git a/Crypto/Hash/__init__.py b/Crypto/Hash/__init__.py deleted file mode 100644 index 719cd8d..0000000 --- a/Crypto/Hash/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -__all__ = ['HMAC', 'MD2', 'MD4', 'MD5', 'RIPEMD160', 'SHA1', - 'SHA224', 'SHA256', 'SHA384', 'SHA512', 'CMAC', 'Poly1305'] diff --git a/Crypto/Hash/__init__.pyi b/Crypto/Hash/__init__.pyi deleted file mode 100644 index e69de29..0000000 diff --git a/Crypto/Hash/__pycache__/BLAKE2s.cpython-36.pyc b/Crypto/Hash/__pycache__/BLAKE2s.cpython-36.pyc deleted file mode 100644 index e74582d..0000000 Binary files a/Crypto/Hash/__pycache__/BLAKE2s.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Hash/__pycache__/CMAC.cpython-36.pyc b/Crypto/Hash/__pycache__/CMAC.cpython-36.pyc deleted file mode 100644 index e838246..0000000 Binary files a/Crypto/Hash/__pycache__/CMAC.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Hash/__pycache__/HMAC.cpython-36.pyc b/Crypto/Hash/__pycache__/HMAC.cpython-36.pyc deleted file mode 100644 index 8ef9b04..0000000 Binary files a/Crypto/Hash/__pycache__/HMAC.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Hash/__pycache__/MD5.cpython-36.pyc b/Crypto/Hash/__pycache__/MD5.cpython-36.pyc deleted file mode 100644 index 9ed2b7e..0000000 Binary files a/Crypto/Hash/__pycache__/MD5.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Hash/__pycache__/SHA1.cpython-36.pyc b/Crypto/Hash/__pycache__/SHA1.cpython-36.pyc deleted file mode 100644 index 007393f..0000000 Binary files a/Crypto/Hash/__pycache__/SHA1.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Hash/__pycache__/SHA256.cpython-36.pyc b/Crypto/Hash/__pycache__/SHA256.cpython-36.pyc deleted file mode 100644 index 9c5bea5..0000000 Binary files a/Crypto/Hash/__pycache__/SHA256.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Hash/__pycache__/__init__.cpython-36.pyc b/Crypto/Hash/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index e00ee4c..0000000 Binary files a/Crypto/Hash/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Hash/_ghash_clmul.abi3.so b/Crypto/Hash/_ghash_clmul.abi3.so deleted file mode 100644 index 7a4dd58..0000000 Binary files a/Crypto/Hash/_ghash_clmul.abi3.so and /dev/null differ diff --git a/Crypto/Hash/_ghash_portable.abi3.so b/Crypto/Hash/_ghash_portable.abi3.so deleted file mode 100644 index eb65f83..0000000 Binary files a/Crypto/Hash/_ghash_portable.abi3.so and /dev/null differ diff --git a/Crypto/Hash/_keccak.abi3.so b/Crypto/Hash/_keccak.abi3.so deleted file mode 100644 index b5b81aa..0000000 Binary files a/Crypto/Hash/_keccak.abi3.so and /dev/null differ diff --git a/Crypto/Hash/_poly1305.abi3.so b/Crypto/Hash/_poly1305.abi3.so deleted file mode 100644 index 27c909d..0000000 Binary files a/Crypto/Hash/_poly1305.abi3.so and /dev/null differ diff --git a/Crypto/Hash/keccak.py b/Crypto/Hash/keccak.py deleted file mode 100644 index 401d5c5..0000000 --- a/Crypto/Hash/keccak.py +++ /dev/null @@ -1,173 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2015, Legrandin -# 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 Crypto.Util.py3compat import bord - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - VoidPointer, SmartPointer, - create_string_buffer, - get_raw_buffer, c_size_t, - c_uint8_ptr) - -_raw_keccak_lib = load_pycryptodome_raw_lib("Crypto.Hash._keccak", - """ - int keccak_init(void **state, - size_t capacity_bytes, - uint8_t padding_byte); - int keccak_destroy(void *state); - int keccak_absorb(void *state, - const uint8_t *in, - size_t len); - int keccak_squeeze(const void *state, - uint8_t *out, - size_t len); - int keccak_digest(void *state, uint8_t *digest, size_t len); - """) - -class Keccak_Hash(object): - """A Keccak hash object. - Do not instantiate directly. - Use the :func:`new` function. - - :ivar digest_size: the size in bytes of the resulting hash - :vartype digest_size: integer - """ - - def __init__(self, data, digest_bytes, update_after_digest): - # The size of the resulting hash in bytes. - self.digest_size = digest_bytes - - self._update_after_digest = update_after_digest - self._digest_done = False - - state = VoidPointer() - result = _raw_keccak_lib.keccak_init(state.address_of(), - c_size_t(self.digest_size * 2), - 0x01) - if result: - raise ValueError("Error %d while instantiating keccak" % result) - self._state = SmartPointer(state.get(), - _raw_keccak_lib.keccak_destroy) - if data: - self.update(data) - - def update(self, data): - """Continue hashing of a message by consuming the next chunk of data. - - Args: - data (byte string/byte array/memoryview): The next chunk of the message being hashed. - """ - - if self._digest_done and not self._update_after_digest: - raise TypeError("You can only call 'digest' or 'hexdigest' on this object") - - result = _raw_keccak_lib.keccak_absorb(self._state.get(), - c_uint8_ptr(data), - c_size_t(len(data))) - if result: - raise ValueError("Error %d while updating keccak" % result) - return self - - def digest(self): - """Return the **binary** (non-printable) digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Binary form. - :rtype: byte string - """ - - self._digest_done = True - bfr = create_string_buffer(self.digest_size) - result = _raw_keccak_lib.keccak_digest(self._state.get(), - bfr, - c_size_t(self.digest_size)) - if result: - raise ValueError("Error %d while squeezing keccak" % result) - - return get_raw_buffer(bfr) - - def hexdigest(self): - """Return the **printable** digest of the message that has been hashed so far. - - :return: The hash digest, computed over the data processed so far. - Hexadecimal encoded. - :rtype: string - """ - - return "".join(["%02x" % bord(x) for x in self.digest()]) - - def new(self, **kwargs): - """Create a fresh Keccak hash object.""" - - if "digest_bytes" not in kwargs and "digest_bits" not in kwargs: - kwargs["digest_bytes"] = self.digest_size - - return new(**kwargs) - - -def new(**kwargs): - """Create a new hash object. - - Args: - data (bytes/bytearray/memoryview): - The very first chunk of the message to hash. - It is equivalent to an early call to :meth:`Keccak_Hash.update`. - digest_bytes (integer): - The size of the digest, in bytes (28, 32, 48, 64). - digest_bits (integer): - The size of the digest, in bits (224, 256, 384, 512). - update_after_digest (boolean): - Whether :meth:`Keccak.digest` can be followed by another - :meth:`Keccak.update` (default: ``False``). - - :Return: A :class:`Keccak_Hash` hash object - """ - - data = kwargs.pop("data", None) - update_after_digest = kwargs.pop("update_after_digest", False) - - digest_bytes = kwargs.pop("digest_bytes", None) - digest_bits = kwargs.pop("digest_bits", None) - if None not in (digest_bytes, digest_bits): - raise TypeError("Only one digest parameter must be provided") - if (None, None) == (digest_bytes, digest_bits): - raise TypeError("Digest size (bits, bytes) not provided") - if digest_bytes is not None: - if digest_bytes not in (28, 32, 48, 64): - raise ValueError("'digest_bytes' must be: 28, 32, 48 or 64") - else: - if digest_bits not in (224, 256, 384, 512): - raise ValueError("'digest_bytes' must be: 224, 256, 384 or 512") - digest_bytes = digest_bits // 8 - - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - return Keccak_Hash(data, digest_bytes, update_after_digest) diff --git a/Crypto/Hash/keccak.pyi b/Crypto/Hash/keccak.pyi deleted file mode 100644 index 844d256..0000000 --- a/Crypto/Hash/keccak.pyi +++ /dev/null @@ -1,23 +0,0 @@ -from typing import Union, Any - -Buffer = Union[bytes, bytearray, memoryview] - -class Keccak_Hash(object): - digest_size: int - def __init__(self, - data: Buffer, - digest_bytes: int, - update_after_digest: bool) -> None: ... - def update(self, data: Buffer) -> Keccak_Hash: ... - def digest(self) -> bytes: ... - def hexdigest(self) -> str: ... - def new(self, - data: Buffer = ..., - digest_bytes: int = ..., - digest_bits: int = ..., - update_after_digest: bool = ...) -> Keccak_Hash: ... - -def new(data: Buffer = ..., - digest_bytes: int = ..., - digest_bits: int = ..., - update_after_digest: bool = ...) -> Keccak_Hash: ... diff --git a/Crypto/IO/PEM.py b/Crypto/IO/PEM.py deleted file mode 100644 index 4c07b25..0000000 --- a/Crypto/IO/PEM.py +++ /dev/null @@ -1,189 +0,0 @@ -# -# Util/PEM.py : Privacy Enhanced Mail utilities -# -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -__all__ = ['encode', 'decode'] - -import re -from binascii import a2b_base64, b2a_base64, hexlify, unhexlify - -from Crypto.Hash import MD5 -from Crypto.Util.Padding import pad, unpad -from Crypto.Cipher import DES, DES3, AES -from Crypto.Protocol.KDF import PBKDF1 -from Crypto.Random import get_random_bytes -from Crypto.Util.py3compat import tobytes, tostr - - -def encode(data, marker, passphrase=None, randfunc=None): - """Encode a piece of binary data into PEM format. - - Args: - data (byte string): - The piece of binary data to encode. - marker (string): - The marker for the PEM block (e.g. "PUBLIC KEY"). - Note that there is no official master list for all allowed markers. - Still, you can refer to the OpenSSL_ source code. - passphrase (byte string): - If given, the PEM block will be encrypted. The key is derived from - the passphrase. - randfunc (callable): - Random number generation function; it accepts an integer N and returns - a byte string of random data, N bytes long. If not given, a new one is - instantiated. - - Returns: - The PEM block, as a string. - - .. _OpenSSL: https://github.com/openssl/openssl/blob/master/include/openssl/pem.h - """ - - if randfunc is None: - randfunc = get_random_bytes - - out = "-----BEGIN %s-----\n" % marker - if passphrase: - # We only support 3DES for encryption - salt = randfunc(8) - key = PBKDF1(passphrase, salt, 16, 1, MD5) - key += PBKDF1(key + passphrase, salt, 8, 1, MD5) - objenc = DES3.new(key, DES3.MODE_CBC, salt) - out += "Proc-Type: 4,ENCRYPTED\nDEK-Info: DES-EDE3-CBC,%s\n\n" %\ - tostr(hexlify(salt).upper()) - # Encrypt with PKCS#7 padding - data = objenc.encrypt(pad(data, objenc.block_size)) - elif passphrase is not None: - raise ValueError("Empty password") - - # Each BASE64 line can take up to 64 characters (=48 bytes of data) - # b2a_base64 adds a new line character! - chunks = [tostr(b2a_base64(data[i:i + 48])) - for i in range(0, len(data), 48)] - out += "".join(chunks) - out += "-----END %s-----" % marker - return out - - -def _EVP_BytesToKey(data, salt, key_len): - d = [ b'' ] - m = (key_len + 15 ) // 16 - for _ in range(m): - nd = MD5.new(d[-1] + data + salt).digest() - d.append(nd) - return b"".join(d)[:key_len] - - -def decode(pem_data, passphrase=None): - """Decode a PEM block into binary. - - Args: - pem_data (string): - The PEM block. - passphrase (byte string): - If given and the PEM block is encrypted, - the key will be derived from the passphrase. - - Returns: - A tuple with the binary data, the marker string, and a boolean to - indicate if decryption was performed. - - Raises: - ValueError: if decoding fails, if the PEM file is encrypted and no passphrase has - been provided or if the passphrase is incorrect. - """ - - # Verify Pre-Encapsulation Boundary - r = re.compile(r"\s*-----BEGIN (.*)-----\s+") - m = r.match(pem_data) - if not m: - raise ValueError("Not a valid PEM pre boundary") - marker = m.group(1) - - # Verify Post-Encapsulation Boundary - r = re.compile(r"-----END (.*)-----\s*$") - m = r.search(pem_data) - if not m or m.group(1) != marker: - raise ValueError("Not a valid PEM post boundary") - - # Removes spaces and slit on lines - lines = pem_data.replace(" ", '').split() - - # Decrypts, if necessary - if lines[1].startswith('Proc-Type:4,ENCRYPTED'): - if not passphrase: - raise ValueError("PEM is encrypted, but no passphrase available") - DEK = lines[2].split(':') - if len(DEK) != 2 or DEK[0] != 'DEK-Info': - raise ValueError("PEM encryption format not supported.") - algo, salt = DEK[1].split(',') - salt = unhexlify(tobytes(salt)) - - padding = True - - if algo == "DES-CBC": - key = _EVP_BytesToKey(passphrase, salt, 8) - objdec = DES.new(key, DES.MODE_CBC, salt) - elif algo == "DES-EDE3-CBC": - key = _EVP_BytesToKey(passphrase, salt, 24) - objdec = DES3.new(key, DES3.MODE_CBC, salt) - elif algo == "AES-128-CBC": - key = _EVP_BytesToKey(passphrase, salt[:8], 16) - objdec = AES.new(key, AES.MODE_CBC, salt) - elif algo == "AES-192-CBC": - key = _EVP_BytesToKey(passphrase, salt[:8], 24) - objdec = AES.new(key, AES.MODE_CBC, salt) - elif algo == "AES-256-CBC": - key = _EVP_BytesToKey(passphrase, salt[:8], 32) - objdec = AES.new(key, AES.MODE_CBC, salt) - elif algo.lower() == "id-aes256-gcm": - key = _EVP_BytesToKey(passphrase, salt[:8], 32) - objdec = AES.new(key, AES.MODE_GCM, nonce=salt) - padding = False - else: - raise ValueError("Unsupport PEM encryption algorithm (%s)." % algo) - lines = lines[2:] - else: - objdec = None - - # Decode body - data = a2b_base64(''.join(lines[1:-1])) - enc_flag = False - if objdec: - if padding: - data = unpad(objdec.decrypt(data), objdec.block_size) - else: - # There is no tag, so we don't use decrypt_and_verify - data = objdec.decrypt(data) - enc_flag = True - - return (data, marker, enc_flag) diff --git a/Crypto/IO/PEM.pyi b/Crypto/IO/PEM.pyi deleted file mode 100644 index 2e324c4..0000000 --- a/Crypto/IO/PEM.pyi +++ /dev/null @@ -1,10 +0,0 @@ -from typing import Tuple, Optional, Callable - -def encode(data: bytes, - marke: str, - passphrase: Optional[bytes] = ..., - randfunc: Optional[Callable[[int],bytes]] = ...) -> str: ... - - -def decode(pem_data: str, - passphrase: Optional[bytes] = ...) -> Tuple[bytes, str, bool]: ... diff --git a/Crypto/IO/PKCS8.py b/Crypto/IO/PKCS8.py deleted file mode 100644 index 3bda834..0000000 --- a/Crypto/IO/PKCS8.py +++ /dev/null @@ -1,231 +0,0 @@ -# -# PublicKey/PKCS8.py : PKCS#8 functions -# -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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 Crypto.Util.py3compat import * - -from Crypto.Util.asn1 import ( - DerNull, - DerSequence, - DerObjectId, - DerOctetString, - ) - -from Crypto.IO._PBES import PBES1, PBES2, PbesError - - -__all__ = ['wrap', 'unwrap'] - - -def wrap(private_key, key_oid, passphrase=None, protection=None, - prot_params=None, key_params=None, randfunc=None): - """Wrap a private key into a PKCS#8 blob (clear or encrypted). - - Args: - - private_key (byte string): - The private key encoded in binary form. The actual encoding is - algorithm specific. In most cases, it is DER. - - key_oid (string): - The object identifier (OID) of the private key to wrap. - It is a dotted string, like ``1.2.840.113549.1.1.1`` (for RSA keys). - - passphrase (bytes string or string): - The secret passphrase from which the wrapping key is derived. - Set it only if encryption is required. - - protection (string): - The identifier of the algorithm to use for securely wrapping the key. - The default value is ``PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC``. - - prot_params (dictionary): - Parameters for the protection algorithm. - - +------------------+-----------------------------------------------+ - | Key | Description | - +==================+===============================================+ - | iteration_count | The KDF algorithm is repeated several times to| - | | slow down brute force attacks on passwords | - | | (called *N* or CPU/memory cost in scrypt). | - | | The default value for PBKDF2 is 1000. | - | | The default value for scrypt is 16384. | - +------------------+-----------------------------------------------+ - | salt_size | Salt is used to thwart dictionary and rainbow | - | | attacks on passwords. The default value is 8 | - | | bytes. | - +------------------+-----------------------------------------------+ - | block_size | *(scrypt only)* Memory-cost (r). The default | - | | value is 8. | - +------------------+-----------------------------------------------+ - | parallelization | *(scrypt only)* CPU-cost (p). The default | - | | value is 1. | - +------------------+-----------------------------------------------+ - - key_params (DER object): - The algorithm parameters associated to the private key. - It is required for algorithms like DSA, but not for others like RSA. - - randfunc (callable): - Random number generation function; it should accept a single integer - N and return a string of random data, N bytes long. - If not specified, a new RNG will be instantiated - from :mod:`Crypto.Random`. - - Return: - The PKCS#8-wrapped private key (possibly encrypted), as a byte string. - """ - - if key_params is None: - key_params = DerNull() - - # - # PrivateKeyInfo ::= SEQUENCE { - # version Version, - # privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - # privateKey PrivateKey, - # attributes [0] IMPLICIT Attributes OPTIONAL - # } - # - pk_info = DerSequence([ - 0, - DerSequence([ - DerObjectId(key_oid), - key_params - ]), - DerOctetString(private_key) - ]) - pk_info_der = pk_info.encode() - - if passphrase is None: - return pk_info_der - - if not passphrase: - raise ValueError("Empty passphrase") - - # Encryption with PBES2 - passphrase = tobytes(passphrase) - if protection is None: - protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC' - return PBES2.encrypt(pk_info_der, passphrase, - protection, prot_params, randfunc) - - -def unwrap(p8_private_key, passphrase=None): - """Unwrap a private key from a PKCS#8 blob (clear or encrypted). - - Args: - p8_private_key (byte string): - The private key wrapped into a PKCS#8 blob, DER encoded. - passphrase (byte string or string): - The passphrase to use to decrypt the blob (if it is encrypted). - - Return: - A tuple containing - - #. the algorithm identifier of the wrapped key (OID, dotted string) - #. the private key (byte string, DER encoded) - #. the associated parameters (byte string, DER encoded) or ``None`` - - Raises: - ValueError : if decoding fails - """ - - if passphrase: - passphrase = tobytes(passphrase) - - found = False - try: - p8_private_key = PBES1.decrypt(p8_private_key, passphrase) - found = True - except PbesError as e: - error_str = "PBES1[%s]" % str(e) - except ValueError: - error_str = "PBES1[Invalid]" - - if not found: - try: - p8_private_key = PBES2.decrypt(p8_private_key, passphrase) - found = True - except PbesError as e: - error_str += ",PBES2[%s]" % str(e) - except ValueError: - error_str += ",PBES2[Invalid]" - - if not found: - raise ValueError("Error decoding PKCS#8 (%s)" % error_str) - - pk_info = DerSequence().decode(p8_private_key, nr_elements=(2, 3, 4)) - if len(pk_info) == 2 and not passphrase: - raise ValueError("Not a valid clear PKCS#8 structure " - "(maybe it is encrypted?)") - - # - # PrivateKeyInfo ::= SEQUENCE { - # version Version, - # privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - # privateKey PrivateKey, - # attributes [0] IMPLICIT Attributes OPTIONAL - # } - # Version ::= INTEGER - if pk_info[0] != 0: - raise ValueError("Not a valid PrivateKeyInfo SEQUENCE") - - # PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier - # - # EncryptedPrivateKeyInfo ::= SEQUENCE { - # encryptionAlgorithm EncryptionAlgorithmIdentifier, - # encryptedData EncryptedData - # } - # EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier - - # AlgorithmIdentifier ::= SEQUENCE { - # algorithm OBJECT IDENTIFIER, - # parameters ANY DEFINED BY algorithm OPTIONAL - # } - - algo = DerSequence().decode(pk_info[1], nr_elements=(1, 2)) - algo_oid = DerObjectId().decode(algo[0]).value - if len(algo) == 1: - algo_params = None - else: - try: - DerNull().decode(algo[1]) - algo_params = None - except: - algo_params = algo[1] - - # EncryptedData ::= OCTET STRING - private_key = DerOctetString().decode(pk_info[2]).payload - - return (algo_oid, private_key, algo_params) diff --git a/Crypto/IO/PKCS8.pyi b/Crypto/IO/PKCS8.pyi deleted file mode 100644 index ad233d4..0000000 --- a/Crypto/IO/PKCS8.pyi +++ /dev/null @@ -1,14 +0,0 @@ -from typing import Dict, Tuple, Optional, Union, Callable - -from Crypto.Util.asn1 import DerObject - -def wrap(private_key: bytes, - key_oid: str, - passphrase: Union[bytes, str] = ..., - protection: str = ..., - prot_params: Dict = ..., - key_params: DerObject = ..., - randfunc: Optional[Callable[[int],str]] = ...) -> bytes: ... - - -def unwrap(p8_private_key: bytes, passphrase: Optional[Union[bytes, str]] = ...) -> Tuple[str, bytes, Optional[bytes]]: ... diff --git a/Crypto/IO/_PBES.py b/Crypto/IO/_PBES.py deleted file mode 100644 index a47c775..0000000 --- a/Crypto/IO/_PBES.py +++ /dev/null @@ -1,435 +0,0 @@ -# -# PublicKey/_PBES.py : Password-Based Encryption functions -# -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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 Crypto import Random -from Crypto.Util.asn1 import ( - DerSequence, DerOctetString, - DerObjectId, DerInteger, - ) - -from Crypto.Util.Padding import pad, unpad -from Crypto.Hash import MD5, SHA1, SHA224, SHA256, SHA384, SHA512 -from Crypto.Cipher import DES, ARC2, DES3, AES -from Crypto.Protocol.KDF import PBKDF1, PBKDF2, scrypt - -_OID_PBE_WITH_MD5_AND_DES_CBC = "1.2.840.113549.1.5.3" -_OID_PBE_WITH_MD5_AND_RC2_CBC = "1.2.840.113549.1.5.6" -_OID_PBE_WITH_SHA1_AND_DES_CBC = "1.2.840.113549.1.5.10" -_OID_PBE_WITH_SHA1_AND_RC2_CBC = "1.2.840.113549.1.5.11" - -_OID_PBES2 = "1.2.840.113549.1.5.13" - -_OID_PBKDF2 = "1.2.840.113549.1.5.12" -_OID_SCRYPT = "1.3.6.1.4.1.11591.4.11" - -_OID_HMAC_SHA1 = "1.2.840.113549.2.7" -_OID_HMAC_SHA224 = "1.2.840.113549.2.8" -_OID_HMAC_SHA256 = "1.2.840.113549.2.9" -_OID_HMAC_SHA384 = "1.2.840.113549.2.10" -_OID_HMAC_SHA512 = "1.2.840.113549.2.11" - -_OID_DES_EDE3_CBC = "1.2.840.113549.3.7" -_OID_AES128_CBC = "2.16.840.1.101.3.4.1.2" -_OID_AES192_CBC = "2.16.840.1.101.3.4.1.22" -_OID_AES256_CBC = "2.16.840.1.101.3.4.1.42" - - -class PbesError(ValueError): - pass - -# These are the ASN.1 definitions used by the PBES1/2 logic: -# -# EncryptedPrivateKeyInfo ::= SEQUENCE { -# encryptionAlgorithm EncryptionAlgorithmIdentifier, -# encryptedData EncryptedData -# } -# -# EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier -# -# EncryptedData ::= OCTET STRING -# -# AlgorithmIdentifier ::= SEQUENCE { -# algorithm OBJECT IDENTIFIER, -# parameters ANY DEFINED BY algorithm OPTIONAL -# } -# -# PBEParameter ::= SEQUENCE { -# salt OCTET STRING (SIZE(8)), -# iterationCount INTEGER -# } -# -# PBES2-params ::= SEQUENCE { -# keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, -# encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} -# } -# -# PBKDF2-params ::= SEQUENCE { -# salt CHOICE { -# specified OCTET STRING, -# otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}} -# }, -# iterationCount INTEGER (1..MAX), -# keyLength INTEGER (1..MAX) OPTIONAL, -# prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 -# } -# -# scrypt-params ::= SEQUENCE { -# salt OCTET STRING, -# costParameter INTEGER (1..MAX), -# blockSize INTEGER (1..MAX), -# parallelizationParameter INTEGER (1..MAX), -# keyLength INTEGER (1..MAX) OPTIONAL -# } - -class PBES1(object): - """Deprecated encryption scheme with password-based key derivation - (originally defined in PKCS#5 v1.5, but still present in `v2.0`__). - - .. __: http://www.ietf.org/rfc/rfc2898.txt - """ - - @staticmethod - def decrypt(data, passphrase): - """Decrypt a piece of data using a passphrase and *PBES1*. - - The algorithm to use is automatically detected. - - :Parameters: - data : byte string - The piece of data to decrypt. - passphrase : byte string - The passphrase to use for decrypting the data. - :Returns: - The decrypted data, as a binary string. - """ - - enc_private_key_info = DerSequence().decode(data) - encrypted_algorithm = DerSequence().decode(enc_private_key_info[0]) - encrypted_data = DerOctetString().decode(enc_private_key_info[1]).payload - - pbe_oid = DerObjectId().decode(encrypted_algorithm[0]).value - cipher_params = {} - if pbe_oid == _OID_PBE_WITH_MD5_AND_DES_CBC: - # PBE_MD5_DES_CBC - hashmod = MD5 - ciphermod = DES - elif pbe_oid == _OID_PBE_WITH_MD5_AND_RC2_CBC: - # PBE_MD5_RC2_CBC - hashmod = MD5 - ciphermod = ARC2 - cipher_params['effective_keylen'] = 64 - elif pbe_oid == _OID_PBE_WITH_SHA1_AND_DES_CBC: - # PBE_SHA1_DES_CBC - hashmod = SHA1 - ciphermod = DES - elif pbe_oid == _OID_PBE_WITH_SHA1_AND_RC2_CBC: - # PBE_SHA1_RC2_CBC - hashmod = SHA1 - ciphermod = ARC2 - cipher_params['effective_keylen'] = 64 - else: - raise PbesError("Unknown OID for PBES1") - - pbe_params = DerSequence().decode(encrypted_algorithm[1], nr_elements=2) - salt = DerOctetString().decode(pbe_params[0]).payload - iterations = pbe_params[1] - - key_iv = PBKDF1(passphrase, salt, 16, iterations, hashmod) - key, iv = key_iv[:8], key_iv[8:] - - cipher = ciphermod.new(key, ciphermod.MODE_CBC, iv, **cipher_params) - pt = cipher.decrypt(encrypted_data) - return unpad(pt, cipher.block_size) - - -class PBES2(object): - """Encryption scheme with password-based key derivation - (defined in `PKCS#5 v2.0`__). - - .. __: http://www.ietf.org/rfc/rfc2898.txt.""" - - @staticmethod - def encrypt(data, passphrase, protection, prot_params=None, randfunc=None): - """Encrypt a piece of data using a passphrase and *PBES2*. - - :Parameters: - data : byte string - The piece of data to encrypt. - passphrase : byte string - The passphrase to use for encrypting the data. - protection : string - The identifier of the encryption algorithm to use. - The default value is '``PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC``'. - prot_params : dictionary - Parameters of the protection algorithm. - - +------------------+-----------------------------------------------+ - | Key | Description | - +==================+===============================================+ - | iteration_count | The KDF algorithm is repeated several times to| - | | slow down brute force attacks on passwords | - | | (called *N* or CPU/memory cost in scrypt). | - | | | - | | The default value for PBKDF2 is 1 000. | - | | The default value for scrypt is 16 384. | - +------------------+-----------------------------------------------+ - | salt_size | Salt is used to thwart dictionary and rainbow | - | | attacks on passwords. The default value is 8 | - | | bytes. | - +------------------+-----------------------------------------------+ - | block_size | *(scrypt only)* Memory-cost (r). The default | - | | value is 8. | - +------------------+-----------------------------------------------+ - | parallelization | *(scrypt only)* CPU-cost (p). The default | - | | value is 1. | - +------------------+-----------------------------------------------+ - - - randfunc : callable - Random number generation function; it should accept - a single integer N and return a string of random data, - N bytes long. If not specified, a new RNG will be - instantiated from ``Crypto.Random``. - - :Returns: - The encrypted data, as a binary string. - """ - - if prot_params is None: - prot_params = {} - - if randfunc is None: - randfunc = Random.new().read - - if protection == 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC': - key_size = 24 - module = DES3 - cipher_mode = DES3.MODE_CBC - enc_oid = _OID_DES_EDE3_CBC - elif protection in ('PBKDF2WithHMAC-SHA1AndAES128-CBC', - 'scryptAndAES128-CBC'): - key_size = 16 - module = AES - cipher_mode = AES.MODE_CBC - enc_oid = _OID_AES128_CBC - elif protection in ('PBKDF2WithHMAC-SHA1AndAES192-CBC', - 'scryptAndAES192-CBC'): - key_size = 24 - module = AES - cipher_mode = AES.MODE_CBC - enc_oid = _OID_AES192_CBC - elif protection in ('PBKDF2WithHMAC-SHA1AndAES256-CBC', - 'scryptAndAES256-CBC'): - key_size = 32 - module = AES - cipher_mode = AES.MODE_CBC - enc_oid = _OID_AES256_CBC - else: - raise ValueError("Unknown PBES2 mode") - - # Get random data - iv = randfunc(module.block_size) - salt = randfunc(prot_params.get("salt_size", 8)) - - # Derive key from password - if protection.startswith('PBKDF2'): - count = prot_params.get("iteration_count", 1000) - key = PBKDF2(passphrase, salt, key_size, count) - kdf_info = DerSequence([ - DerObjectId(_OID_PBKDF2), # PBKDF2 - DerSequence([ - DerOctetString(salt), - DerInteger(count) - ]) - ]) - else: - # It must be scrypt - count = prot_params.get("iteration_count", 16384) - scrypt_r = prot_params.get('block_size', 8) - scrypt_p = prot_params.get('parallelization', 1) - key = scrypt(passphrase, salt, key_size, - count, scrypt_r, scrypt_p) - kdf_info = DerSequence([ - DerObjectId(_OID_SCRYPT), # scrypt - DerSequence([ - DerOctetString(salt), - DerInteger(count), - DerInteger(scrypt_r), - DerInteger(scrypt_p) - ]) - ]) - - # Create cipher and use it - cipher = module.new(key, cipher_mode, iv) - encrypted_data = cipher.encrypt(pad(data, cipher.block_size)) - enc_info = DerSequence([ - DerObjectId(enc_oid), - DerOctetString(iv) - ]) - - # Result - enc_private_key_info = DerSequence([ - # encryptionAlgorithm - DerSequence([ - DerObjectId(_OID_PBES2), - DerSequence([ - kdf_info, - enc_info - ]), - ]), - DerOctetString(encrypted_data) - ]) - return enc_private_key_info.encode() - - @staticmethod - def decrypt(data, passphrase): - """Decrypt a piece of data using a passphrase and *PBES2*. - - The algorithm to use is automatically detected. - - :Parameters: - data : byte string - The piece of data to decrypt. - passphrase : byte string - The passphrase to use for decrypting the data. - :Returns: - The decrypted data, as a binary string. - """ - - enc_private_key_info = DerSequence().decode(data, nr_elements=2) - enc_algo = DerSequence().decode(enc_private_key_info[0]) - encrypted_data = DerOctetString().decode(enc_private_key_info[1]).payload - - pbe_oid = DerObjectId().decode(enc_algo[0]).value - if pbe_oid != _OID_PBES2: - raise PbesError("Not a PBES2 object") - - pbes2_params = DerSequence().decode(enc_algo[1], nr_elements=2) - - ### Key Derivation Function selection - kdf_info = DerSequence().decode(pbes2_params[0], nr_elements=2) - kdf_oid = DerObjectId().decode(kdf_info[0]).value - - kdf_key_length = None - - # We only support PBKDF2 or scrypt - if kdf_oid == _OID_PBKDF2: - - pbkdf2_params = DerSequence().decode(kdf_info[1], nr_elements=(2, 3, 4)) - salt = DerOctetString().decode(pbkdf2_params[0]).payload - iteration_count = pbkdf2_params[1] - - left = len(pbkdf2_params) - 2 - idx = 2 - - if left > 0: - try: - kdf_key_length = pbkdf2_params[idx] - 0 - left -= 1 - idx += 1 - except TypeError: - pass - - # Default is HMAC-SHA1 - pbkdf2_prf_oid = "1.2.840.113549.2.7" - if left > 0: - pbkdf2_prf_algo_id = DerSequence().decode(pbkdf2_params[idx]) - pbkdf2_prf_oid = DerObjectId().decode(pbkdf2_prf_algo_id[0]).value - - elif kdf_oid == _OID_SCRYPT: - - scrypt_params = DerSequence().decode(kdf_info[1], nr_elements=(4, 5)) - salt = DerOctetString().decode(scrypt_params[0]).payload - iteration_count, scrypt_r, scrypt_p = [scrypt_params[x] - for x in (1, 2, 3)] - if len(scrypt_params) > 4: - kdf_key_length = scrypt_params[4] - else: - kdf_key_length = None - else: - raise PbesError("Unsupported PBES2 KDF") - - ### Cipher selection - enc_info = DerSequence().decode(pbes2_params[1]) - enc_oid = DerObjectId().decode(enc_info[0]).value - - if enc_oid == _OID_DES_EDE3_CBC: - # DES_EDE3_CBC - ciphermod = DES3 - key_size = 24 - elif enc_oid == _OID_AES128_CBC: - # AES128_CBC - ciphermod = AES - key_size = 16 - elif enc_oid == _OID_AES192_CBC: - # AES192_CBC - ciphermod = AES - key_size = 24 - elif enc_oid == _OID_AES256_CBC: - # AES256_CBC - ciphermod = AES - key_size = 32 - else: - raise PbesError("Unsupported PBES2 cipher") - - if kdf_key_length and kdf_key_length != key_size: - raise PbesError("Mismatch between PBES2 KDF parameters" - " and selected cipher") - - IV = DerOctetString().decode(enc_info[1]).payload - - # Create cipher - if kdf_oid == _OID_PBKDF2: - if pbkdf2_prf_oid == _OID_HMAC_SHA1: - hmac_hash_module = SHA1 - elif pbkdf2_prf_oid == _OID_HMAC_SHA224: - hmac_hash_module = SHA224 - elif pbkdf2_prf_oid == _OID_HMAC_SHA256: - hmac_hash_module = SHA256 - elif pbkdf2_prf_oid == _OID_HMAC_SHA384: - hmac_hash_module = SHA384 - elif pbkdf2_prf_oid == _OID_HMAC_SHA512: - hmac_hash_module = SHA512 - else: - raise PbesError("Unsupported HMAC %s" % pbkdf2_prf_oid) - - key = PBKDF2(passphrase, salt, key_size, iteration_count, - hmac_hash_module=hmac_hash_module) - else: - key = scrypt(passphrase, salt, key_size, iteration_count, - scrypt_r, scrypt_p) - cipher = ciphermod.new(key, ciphermod.MODE_CBC, IV) - - # Decrypt data - pt = cipher.decrypt(encrypted_data) - return unpad(pt, cipher.block_size) diff --git a/Crypto/IO/_PBES.pyi b/Crypto/IO/_PBES.pyi deleted file mode 100644 index a8a34ce..0000000 --- a/Crypto/IO/_PBES.pyi +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Dict, Optional, Callable - -class PbesError(ValueError): - ... - -class PBES1(object): - @staticmethod - def decrypt(data: bytes, passphrase: bytes) -> bytes: ... - -class PBES2(object): - @staticmethod - def encrypt(data: bytes, - passphrase: bytes, - protection: str, - prot_params: Optional[Dict] = ..., - randfunc: Optional[Callable[[int],bytes]] = ...) -> bytes: ... - - @staticmethod - def decrypt(data:bytes, passphrase: bytes) -> bytes: ... diff --git a/Crypto/IO/__init__.py b/Crypto/IO/__init__.py deleted file mode 100644 index 85a0d0b..0000000 --- a/Crypto/IO/__init__.py +++ /dev/null @@ -1,31 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -__all__ = ['PEM', 'PKCS8'] diff --git a/Crypto/Math/Numbers.py b/Crypto/Math/Numbers.py deleted file mode 100644 index c2c4483..0000000 --- a/Crypto/Math/Numbers.py +++ /dev/null @@ -1,42 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -__all__ = ["Integer"] - -try: - from Crypto.Math._IntegerGMP import IntegerGMP as Integer - from Crypto.Math._IntegerGMP import implementation as _implementation -except (ImportError, OSError, AttributeError): - try: - from Crypto.Math._IntegerCustom import IntegerCustom as Integer - from Crypto.Math._IntegerCustom import implementation as _implementation - except (ImportError, OSError): - from Crypto.Math._IntegerNative import IntegerNative as Integer - _implementation = {} diff --git a/Crypto/Math/Numbers.pyi b/Crypto/Math/Numbers.pyi deleted file mode 100644 index 126268c..0000000 --- a/Crypto/Math/Numbers.pyi +++ /dev/null @@ -1,4 +0,0 @@ -from Crypto.Math._IntegerBase import IntegerBase - -class Integer(IntegerBase): - pass diff --git a/Crypto/Math/Primality.py b/Crypto/Math/Primality.py deleted file mode 100644 index 884c418..0000000 --- a/Crypto/Math/Primality.py +++ /dev/null @@ -1,369 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -"""Functions to create and test prime numbers. - -:undocumented: __package__ -""" - -from Crypto import Random -from Crypto.Math.Numbers import Integer - -from Crypto.Util.py3compat import iter_range - -COMPOSITE = 0 -PROBABLY_PRIME = 1 - - -def miller_rabin_test(candidate, iterations, randfunc=None): - """Perform a Miller-Rabin primality test on an integer. - - The test is specified in Section C.3.1 of `FIPS PUB 186-4`__. - - :Parameters: - candidate : integer - The number to test for primality. - iterations : integer - The maximum number of iterations to perform before - declaring a candidate a probable prime. - randfunc : callable - An RNG function where bases are taken from. - - :Returns: - ``Primality.COMPOSITE`` or ``Primality.PROBABLY_PRIME``. - - .. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - """ - - if not isinstance(candidate, Integer): - candidate = Integer(candidate) - - if candidate in (1, 2, 3, 5): - return PROBABLY_PRIME - - if candidate.is_even(): - return COMPOSITE - - one = Integer(1) - minus_one = Integer(candidate - 1) - - if randfunc is None: - randfunc = Random.new().read - - # Step 1 and 2 - m = Integer(minus_one) - a = 0 - while m.is_even(): - m >>= 1 - a += 1 - - # Skip step 3 - - # Step 4 - for i in iter_range(iterations): - - # Step 4.1-2 - base = 1 - while base in (one, minus_one): - base = Integer.random_range(min_inclusive=2, - max_inclusive=candidate - 2, - randfunc=randfunc) - assert(2 <= base <= candidate - 2) - - # Step 4.3-4.4 - z = pow(base, m, candidate) - if z in (one, minus_one): - continue - - # Step 4.5 - for j in iter_range(1, a): - z = pow(z, 2, candidate) - if z == minus_one: - break - if z == one: - return COMPOSITE - else: - return COMPOSITE - - # Step 5 - return PROBABLY_PRIME - - -def lucas_test(candidate): - """Perform a Lucas primality test on an integer. - - The test is specified in Section C.3.3 of `FIPS PUB 186-4`__. - - :Parameters: - candidate : integer - The number to test for primality. - - :Returns: - ``Primality.COMPOSITE`` or ``Primality.PROBABLY_PRIME``. - - .. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - """ - - if not isinstance(candidate, Integer): - candidate = Integer(candidate) - - # Step 1 - if candidate in (1, 2, 3, 5): - return PROBABLY_PRIME - if candidate.is_even() or candidate.is_perfect_square(): - return COMPOSITE - - # Step 2 - def alternate(): - value = 5 - while True: - yield value - if value > 0: - value += 2 - else: - value -= 2 - value = -value - - for D in alternate(): - if candidate in (D, -D): - continue - js = Integer.jacobi_symbol(D, candidate) - if js == 0: - return COMPOSITE - if js == -1: - break - # Found D. P=1 and Q=(1-D)/4 (note that Q is guaranteed to be an integer) - - # Step 3 - # This is \delta(n) = n - jacobi(D/n) - K = candidate + 1 - # Step 4 - r = K.size_in_bits() - 1 - # Step 5 - # U_1=1 and V_1=P - U_i = Integer(1) - V_i = Integer(1) - U_temp = Integer(0) - V_temp = Integer(0) - # Step 6 - for i in iter_range(r - 1, -1, -1): - # Square - # U_temp = U_i * V_i % candidate - U_temp.set(U_i) - U_temp *= V_i - U_temp %= candidate - # V_temp = (((V_i ** 2 + (U_i ** 2 * D)) * K) >> 1) % candidate - V_temp.set(U_i) - V_temp *= U_i - V_temp *= D - V_temp.multiply_accumulate(V_i, V_i) - if V_temp.is_odd(): - V_temp += candidate - V_temp >>= 1 - V_temp %= candidate - # Multiply - if K.get_bit(i): - # U_i = (((U_temp + V_temp) * K) >> 1) % candidate - U_i.set(U_temp) - U_i += V_temp - if U_i.is_odd(): - U_i += candidate - U_i >>= 1 - U_i %= candidate - # V_i = (((V_temp + U_temp * D) * K) >> 1) % candidate - V_i.set(V_temp) - V_i.multiply_accumulate(U_temp, D) - if V_i.is_odd(): - V_i += candidate - V_i >>= 1 - V_i %= candidate - else: - U_i.set(U_temp) - V_i.set(V_temp) - # Step 7 - if U_i == 0: - return PROBABLY_PRIME - return COMPOSITE - - -from Crypto.Util.number import sieve_base as _sieve_base_large -## The optimal number of small primes to use for the sieve -## is probably dependent on the platform and the candidate size -_sieve_base = set(_sieve_base_large[:100]) - - -def test_probable_prime(candidate, randfunc=None): - """Test if a number is prime. - - A number is qualified as prime if it passes a certain - number of Miller-Rabin tests (dependent on the size - of the number, but such that probability of a false - positive is less than 10^-30) and a single Lucas test. - - For instance, a 1024-bit candidate will need to pass - 4 Miller-Rabin tests. - - :Parameters: - candidate : integer - The number to test for primality. - randfunc : callable - The routine to draw random bytes from to select Miller-Rabin bases. - :Returns: - ``PROBABLE_PRIME`` if the number if prime with very high probability. - ``COMPOSITE`` if the number is a composite. - For efficiency reasons, ``COMPOSITE`` is also returned for small primes. - """ - - if randfunc is None: - randfunc = Random.new().read - - if not isinstance(candidate, Integer): - candidate = Integer(candidate) - - # First, check trial division by the smallest primes - if int(candidate) in _sieve_base: - return PROBABLY_PRIME - try: - map(candidate.fail_if_divisible_by, _sieve_base) - except ValueError: - return COMPOSITE - - # These are the number of Miller-Rabin iterations s.t. p(k, t) < 1E-30, - # with p(k, t) being the probability that a randomly chosen k-bit number - # is composite but still survives t MR iterations. - mr_ranges = ((220, 30), (280, 20), (390, 15), (512, 10), - (620, 7), (740, 6), (890, 5), (1200, 4), - (1700, 3), (3700, 2)) - - bit_size = candidate.size_in_bits() - try: - mr_iterations = list(filter(lambda x: bit_size < x[0], - mr_ranges))[0][1] - except IndexError: - mr_iterations = 1 - - if miller_rabin_test(candidate, mr_iterations, - randfunc=randfunc) == COMPOSITE: - return COMPOSITE - if lucas_test(candidate) == COMPOSITE: - return COMPOSITE - return PROBABLY_PRIME - - -def generate_probable_prime(**kwargs): - """Generate a random probable prime. - - The prime will not have any specific properties - (e.g. it will not be a *strong* prime). - - Random numbers are evaluated for primality until one - passes all tests, consisting of a certain number of - Miller-Rabin tests with random bases followed by - a single Lucas test. - - The number of Miller-Rabin iterations is chosen such that - the probability that the output number is a non-prime is - less than 1E-30 (roughly 2^{-100}). - - This approach is compliant to `FIPS PUB 186-4`__. - - :Keywords: - exact_bits : integer - The desired size in bits of the probable prime. - It must be at least 160. - randfunc : callable - An RNG function where candidate primes are taken from. - prime_filter : callable - A function that takes an Integer as parameter and returns - True if the number can be passed to further primality tests, - False if it should be immediately discarded. - - :Return: - A probable prime in the range 2^exact_bits > p > 2^(exact_bits-1). - - .. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - """ - - exact_bits = kwargs.pop("exact_bits", None) - randfunc = kwargs.pop("randfunc", None) - prime_filter = kwargs.pop("prime_filter", lambda x: True) - if kwargs: - raise ValueError("Unknown parameters: " + kwargs.keys()) - - if exact_bits is None: - raise ValueError("Missing exact_bits parameter") - if exact_bits < 160: - raise ValueError("Prime number is not big enough.") - - if randfunc is None: - randfunc = Random.new().read - - result = COMPOSITE - while result == COMPOSITE: - candidate = Integer.random(exact_bits=exact_bits, - randfunc=randfunc) | 1 - if not prime_filter(candidate): - continue - result = test_probable_prime(candidate, randfunc) - return candidate - - -def generate_probable_safe_prime(**kwargs): - """Generate a random, probable safe prime. - - Note this operation is much slower than generating a simple prime. - - :Keywords: - exact_bits : integer - The desired size in bits of the probable safe prime. - randfunc : callable - An RNG function where candidate primes are taken from. - - :Return: - A probable safe prime in the range - 2^exact_bits > p > 2^(exact_bits-1). - """ - - exact_bits = kwargs.pop("exact_bits", None) - randfunc = kwargs.pop("randfunc", None) - if kwargs: - raise ValueError("Unknown parameters: " + kwargs.keys()) - - if randfunc is None: - randfunc = Random.new().read - - result = COMPOSITE - while result == COMPOSITE: - q = generate_probable_prime(exact_bits=exact_bits - 1, randfunc=randfunc) - candidate = q * 2 + 1 - if candidate.size_in_bits() != exact_bits: - continue - result = test_probable_prime(candidate, randfunc=randfunc) - return candidate diff --git a/Crypto/Math/Primality.pyi b/Crypto/Math/Primality.pyi deleted file mode 100644 index 7813483..0000000 --- a/Crypto/Math/Primality.pyi +++ /dev/null @@ -1,18 +0,0 @@ -from typing import Callable, Optional, Union, Set - -PrimeResult = int - -COMPOSITE: PrimeResult -PROBABLY_PRIME: PrimeResult - -def miller_rabin_test(candidate: int, iterations: int, randfunc: Optional[Callable[[int],bytes]]=None) -> PrimeResult: ... -def lucas_test(candidate: int) -> PrimeResult: ... -_sieve_base: Set[int] -def test_probable_prime(candidate: int, randfunc: Optional[Callable[[int],bytes]]=None) -> PrimeResult: ... -def generate_probable_prime(*, - exact_bits: int = ..., - randfunc: Callable[[int],bytes] = ..., - prime_filter: Callable[[int],bool] = ...) -> int: ... -def generate_probable_safe_prime(*, - exact_bits: int = ..., - randfunc: Callable[[int],bytes] = ...) -> int: ... diff --git a/Crypto/Math/_IntegerBase.py b/Crypto/Math/_IntegerBase.py deleted file mode 100644 index 48e8f48..0000000 --- a/Crypto/Math/_IntegerBase.py +++ /dev/null @@ -1,392 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2018, Helder Eijs -# 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 abc - -from Crypto.Util.py3compat import iter_range, bord, bchr, ABC - -from Crypto import Random - - -class IntegerBase(ABC): - - # Conversions - @abc.abstractmethod - def __int__(self): - pass - - @abc.abstractmethod - def __str__(self): - pass - - @abc.abstractmethod - def __repr__(self): - pass - - @abc.abstractmethod - def to_bytes(self, block_size=0): - pass - - @staticmethod - @abc.abstractmethod - def from_bytes(byte_string): - pass - - # Relations - @abc.abstractmethod - def __eq__(self, term): - pass - - @abc.abstractmethod - def __ne__(self, term): - pass - - @abc.abstractmethod - def __lt__(self, term): - pass - - @abc.abstractmethod - def __le__(self, term): - pass - - @abc.abstractmethod - def __gt__(self, term): - pass - - @abc.abstractmethod - def __ge__(self, term): - pass - - @abc.abstractmethod - def __nonzero__(self): - pass - __bool__ = __nonzero__ - - @abc.abstractmethod - def is_negative(self): - pass - - # Arithmetic operations - @abc.abstractmethod - def __add__(self, term): - pass - - @abc.abstractmethod - def __sub__(self, term): - pass - - @abc.abstractmethod - def __mul__(self, factor): - pass - - @abc.abstractmethod - def __floordiv__(self, divisor): - pass - - @abc.abstractmethod - def __mod__(self, divisor): - pass - - @abc.abstractmethod - def inplace_pow(self, exponent, modulus=None): - pass - - @abc.abstractmethod - def __pow__(self, exponent, modulus=None): - pass - - @abc.abstractmethod - def __abs__(self): - pass - - @abc.abstractmethod - def sqrt(self, modulus=None): - pass - - @abc.abstractmethod - def __iadd__(self, term): - pass - - @abc.abstractmethod - def __isub__(self, term): - pass - - @abc.abstractmethod - def __imul__(self, term): - pass - - @abc.abstractmethod - def __imod__(self, term): - pass - - # Boolean/bit operations - @abc.abstractmethod - def __and__(self, term): - pass - - @abc.abstractmethod - def __or__(self, term): - pass - - @abc.abstractmethod - def __rshift__(self, pos): - pass - - @abc.abstractmethod - def __irshift__(self, pos): - pass - - @abc.abstractmethod - def __lshift__(self, pos): - pass - - @abc.abstractmethod - def __ilshift__(self, pos): - pass - - @abc.abstractmethod - def get_bit(self, n): - pass - - # Extra - @abc.abstractmethod - def is_odd(self): - pass - - @abc.abstractmethod - def is_even(self): - pass - - @abc.abstractmethod - def size_in_bits(self): - pass - - @abc.abstractmethod - def size_in_bytes(self): - pass - - @abc.abstractmethod - def is_perfect_square(self): - pass - - @abc.abstractmethod - def fail_if_divisible_by(self, small_prime): - pass - - @abc.abstractmethod - def multiply_accumulate(self, a, b): - pass - - @abc.abstractmethod - def set(self, source): - pass - - @abc.abstractmethod - def inplace_inverse(self, modulus): - pass - - @abc.abstractmethod - def inverse(self, modulus): - pass - - @abc.abstractmethod - def gcd(self, term): - pass - - @abc.abstractmethod - def lcm(self, term): - pass - - @staticmethod - @abc.abstractmethod - def jacobi_symbol(a, n): - pass - - @staticmethod - def _tonelli_shanks(n, p): - """Tonelli-shanks algorithm for computing the square root - of n modulo a prime p. - - n must be in the range [0..p-1]. - p must be at least even. - - The return value r is the square root of modulo p. If non-zero, - another solution will also exist (p-r). - - Note we cannot assume that p is really a prime: if it's not, - we can either raise an exception or return the correct value. - """ - - # See https://rosettacode.org/wiki/Tonelli-Shanks_algorithm - - if n in (0, 1): - return n - - if p % 4 == 3: - root = pow(n, (p + 1) // 4, p) - if pow(root, 2, p) != n: - raise ValueError("Cannot compute square root") - return root - - s = 1 - q = (p - 1) // 2 - while not (q & 1): - s += 1 - q >>= 1 - - z = n.__class__(2) - while True: - euler = pow(z, (p - 1) // 2, p) - if euler == 1: - z += 1 - continue - if euler == p - 1: - break - # Most probably p is not a prime - raise ValueError("Cannot compute square root") - - m = s - c = pow(z, q, p) - t = pow(n, q, p) - r = pow(n, (q + 1) // 2, p) - - while t != 1: - for i in iter_range(0, m): - if pow(t, 2**i, p) == 1: - break - if i == m: - raise ValueError("Cannot compute square root of %d mod %d" % (n, p)) - b = pow(c, 2**(m - i - 1), p) - m = i - c = b**2 % p - t = (t * b**2) % p - r = (r * b) % p - - if pow(r, 2, p) != n: - raise ValueError("Cannot compute square root") - - return r - - @classmethod - def random(cls, **kwargs): - """Generate a random natural integer of a certain size. - - :Keywords: - exact_bits : positive integer - The length in bits of the resulting random Integer number. - The number is guaranteed to fulfil the relation: - - 2^bits > result >= 2^(bits - 1) - - max_bits : positive integer - The maximum length in bits of the resulting random Integer number. - The number is guaranteed to fulfil the relation: - - 2^bits > result >=0 - - randfunc : callable - A function that returns a random byte string. The length of the - byte string is passed as parameter. Optional. - If not provided (or ``None``), randomness is read from the system RNG. - - :Return: a Integer object - """ - - exact_bits = kwargs.pop("exact_bits", None) - max_bits = kwargs.pop("max_bits", None) - randfunc = kwargs.pop("randfunc", None) - - if randfunc is None: - randfunc = Random.new().read - - if exact_bits is None and max_bits is None: - raise ValueError("Either 'exact_bits' or 'max_bits' must be specified") - - if exact_bits is not None and max_bits is not None: - raise ValueError("'exact_bits' and 'max_bits' are mutually exclusive") - - bits = exact_bits or max_bits - bytes_needed = ((bits - 1) // 8) + 1 - significant_bits_msb = 8 - (bytes_needed * 8 - bits) - msb = bord(randfunc(1)[0]) - if exact_bits is not None: - msb |= 1 << (significant_bits_msb - 1) - msb &= (1 << significant_bits_msb) - 1 - - return cls.from_bytes(bchr(msb) + randfunc(bytes_needed - 1)) - - @classmethod - def random_range(cls, **kwargs): - """Generate a random integer within a given internal. - - :Keywords: - min_inclusive : integer - The lower end of the interval (inclusive). - max_inclusive : integer - The higher end of the interval (inclusive). - max_exclusive : integer - The higher end of the interval (exclusive). - randfunc : callable - A function that returns a random byte string. The length of the - byte string is passed as parameter. Optional. - If not provided (or ``None``), randomness is read from the system RNG. - :Returns: - An Integer randomly taken in the given interval. - """ - - min_inclusive = kwargs.pop("min_inclusive", None) - max_inclusive = kwargs.pop("max_inclusive", None) - max_exclusive = kwargs.pop("max_exclusive", None) - randfunc = kwargs.pop("randfunc", None) - - if kwargs: - raise ValueError("Unknown keywords: " + str(kwargs.keys)) - if None not in (max_inclusive, max_exclusive): - raise ValueError("max_inclusive and max_exclusive cannot be both" - " specified") - if max_exclusive is not None: - max_inclusive = max_exclusive - 1 - if None in (min_inclusive, max_inclusive): - raise ValueError("Missing keyword to identify the interval") - - if randfunc is None: - randfunc = Random.new().read - - norm_maximum = max_inclusive - min_inclusive - bits_needed = cls(norm_maximum).size_in_bits() - - norm_candidate = -1 - while not 0 <= norm_candidate <= norm_maximum: - norm_candidate = cls.random( - max_bits=bits_needed, - randfunc=randfunc - ) - return norm_candidate + min_inclusive - diff --git a/Crypto/Math/_IntegerBase.pyi b/Crypto/Math/_IntegerBase.pyi deleted file mode 100644 index 3f534db..0000000 --- a/Crypto/Math/_IntegerBase.pyi +++ /dev/null @@ -1,61 +0,0 @@ -from typing import Optional, Union, Callable - -RandFunc = Callable[[int],int] - -class IntegerBase: - - def __int__(self) -> int: ... - def __str__(self) -> str: ... - def __repr__(self) -> str: ... - def to_bytes(self, block_size: Optional[int]=0) -> bytes: ... - @staticmethod - def from_bytes(byte_string: bytes) -> IntegerBase: ... - def __eq__(self, term: object) -> bool: ... - def __ne__(self, term: object) -> bool: ... - def __lt__(self, term: Union[IntegerBase, int]) -> bool: ... - def __le__(self, term: Union[IntegerBase, int]) -> bool: ... - def __gt__(self, term: Union[IntegerBase, int]) -> bool: ... - def __ge__(self, term: Union[IntegerBase, int]) -> bool: ... - def __nonzero__(self) -> bool: ... - def is_negative(self) -> bool: ... - def __add__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __sub__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __mul__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __floordiv__(self, divisor: Union[IntegerBase, int]) -> IntegerBase: ... - def __mod__(self, divisor: Union[IntegerBase, int]) -> IntegerBase: ... - def inplace_pow(self, exponent: int, modulus: Optional[Union[IntegerBase, int]]=None) -> IntegerBase: ... - def __pow__(self, exponent: int, modulus: Optional[int]) -> IntegerBase: ... - def __abs__(self) -> IntegerBase: ... - def sqrt(self, modulus: Optional[int]) -> IntegerBase: ... - def __iadd__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __isub__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __imul__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __imod__(self, divisor: Union[IntegerBase, int]) -> IntegerBase: ... - def __and__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __or__(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def __rshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ... - def __irshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ... - def __lshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ... - def __ilshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ... - def get_bit(self, n: int) -> bool: ... - def is_odd(self) -> bool: ... - def is_even(self) -> bool: ... - def size_in_bits(self) -> int: ... - def size_in_bytes(self) -> int: ... - def is_perfect_square(self) -> bool: ... - def fail_if_divisible_by(self, small_prime: Union[IntegerBase, int]) -> None: ... - def multiply_accumulate(self, a: Union[IntegerBase, int], b: Union[IntegerBase, int]) -> IntegerBase: ... - def set(self, source: Union[IntegerBase, int]) -> IntegerBase: ... - def inplace_inverse(self, modulus: Union[IntegerBase, int]) -> IntegerBase: ... - def inverse(self, modulus: Union[IntegerBase, int]) -> IntegerBase: ... - def gcd(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - def lcm(self, term: Union[IntegerBase, int]) -> IntegerBase: ... - @staticmethod - def jacobi_symbol(a: Union[IntegerBase, int], n: Union[IntegerBase, int]) -> IntegerBase: ... - @staticmethod - def _tonelli_shanks(n: Union[IntegerBase, int], p: Union[IntegerBase, int]) -> IntegerBase : ... - @classmethod - def random(cls, **kwargs: Union[int,RandFunc]) -> IntegerBase : ... - @classmethod - def random_range(cls, **kwargs: Union[int,RandFunc]) -> IntegerBase : ... - diff --git a/Crypto/Math/_IntegerCustom.py b/Crypto/Math/_IntegerCustom.py deleted file mode 100644 index 3ed1dda..0000000 --- a/Crypto/Math/_IntegerCustom.py +++ /dev/null @@ -1,111 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2018, Helder Eijs -# 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 ._IntegerNative import IntegerNative - -from Crypto.Util.number import long_to_bytes, bytes_to_long - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - create_string_buffer, - get_raw_buffer, backend, - c_size_t, c_ulonglong) - - -from Crypto.Random.random import getrandbits - -c_defs = """ -int monty_pow(const uint8_t *base, - const uint8_t *exp, - const uint8_t *modulus, - uint8_t *out, - size_t len, - uint64_t seed); -""" - - -_raw_montgomery = load_pycryptodome_raw_lib("Crypto.Math._modexp", c_defs) -implementation = {"library": "custom", "api": backend} - - -class IntegerCustom(IntegerNative): - - @staticmethod - def from_bytes(byte_string): - return IntegerCustom(bytes_to_long(byte_string)) - - def inplace_pow(self, exponent, modulus=None): - exp_value = int(exponent) - if exp_value < 0: - raise ValueError("Exponent must not be negative") - - # No modular reduction - if modulus is None: - self._value = pow(self._value, exp_value) - return self - - # With modular reduction - mod_value = int(modulus) - if mod_value < 0: - raise ValueError("Modulus must be positive") - if mod_value == 0: - raise ZeroDivisionError("Modulus cannot be zero") - - # C extension only works with odd moduli - if (mod_value & 1) == 0: - self._value = pow(self._value, exp_value, mod_value) - return self - - # C extension only works with bases smaller than modulus - if self._value >= mod_value: - self._value %= mod_value - - max_len = len(long_to_bytes(max(self._value, exp_value, mod_value))) - - base_b = long_to_bytes(self._value, max_len) - exp_b = long_to_bytes(exp_value, max_len) - modulus_b = long_to_bytes(mod_value, max_len) - - out = create_string_buffer(max_len) - - error = _raw_montgomery.monty_pow( - out, - base_b, - exp_b, - modulus_b, - c_size_t(max_len), - c_ulonglong(getrandbits(64)) - ) - - if error: - raise ValueError("monty_pow failed with error: %d" % error) - - result = bytes_to_long(get_raw_buffer(out)) - self._value = result - return self diff --git a/Crypto/Math/_IntegerCustom.pyi b/Crypto/Math/_IntegerCustom.pyi deleted file mode 100644 index 2dd75c7..0000000 --- a/Crypto/Math/_IntegerCustom.pyi +++ /dev/null @@ -1,8 +0,0 @@ -from typing import Any - -from ._IntegerNative import IntegerNative - -_raw_montgomery = Any - -class IntegerCustom(IntegerNative): - pass diff --git a/Crypto/Math/_IntegerGMP.py b/Crypto/Math/_IntegerGMP.py deleted file mode 100644 index a231e9d..0000000 --- a/Crypto/Math/_IntegerGMP.py +++ /dev/null @@ -1,708 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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 sys - -from Crypto.Util.py3compat import tobytes, is_native_int - -from Crypto.Util._raw_api import (backend, load_lib, - get_raw_buffer, get_c_string, - null_pointer, create_string_buffer, - c_ulong, c_size_t) - -from ._IntegerBase import IntegerBase - -gmp_defs = """typedef unsigned long UNIX_ULONG; - typedef struct { int a; int b; void *c; } MPZ; - typedef MPZ mpz_t[1]; - typedef UNIX_ULONG mp_bitcnt_t; - void __gmpz_init (mpz_t x); - void __gmpz_init_set (mpz_t rop, const mpz_t op); - void __gmpz_init_set_ui (mpz_t rop, UNIX_ULONG op); - int __gmp_sscanf (const char *s, const char *fmt, ...); - void __gmpz_set (mpz_t rop, const mpz_t op); - int __gmp_snprintf (uint8_t *buf, size_t size, const char *fmt, ...); - void __gmpz_add (mpz_t rop, const mpz_t op1, const mpz_t op2); - void __gmpz_add_ui (mpz_t rop, const mpz_t op1, UNIX_ULONG op2); - void __gmpz_sub_ui (mpz_t rop, const mpz_t op1, UNIX_ULONG op2); - void __gmpz_addmul (mpz_t rop, const mpz_t op1, const mpz_t op2); - void __gmpz_addmul_ui (mpz_t rop, const mpz_t op1, UNIX_ULONG op2); - void __gmpz_submul_ui (mpz_t rop, const mpz_t op1, UNIX_ULONG op2); - void __gmpz_import (mpz_t rop, size_t count, int order, size_t size, - int endian, size_t nails, const void *op); - void * __gmpz_export (void *rop, size_t *countp, int order, - size_t size, - int endian, size_t nails, const mpz_t op); - size_t __gmpz_sizeinbase (const mpz_t op, int base); - void __gmpz_sub (mpz_t rop, const mpz_t op1, const mpz_t op2); - void __gmpz_mul (mpz_t rop, const mpz_t op1, const mpz_t op2); - void __gmpz_mul_ui (mpz_t rop, const mpz_t op1, UNIX_ULONG op2); - int __gmpz_cmp (const mpz_t op1, const mpz_t op2); - void __gmpz_powm (mpz_t rop, const mpz_t base, const mpz_t exp, const - mpz_t mod); - void __gmpz_powm_ui (mpz_t rop, const mpz_t base, UNIX_ULONG exp, - const mpz_t mod); - void __gmpz_pow_ui (mpz_t rop, const mpz_t base, UNIX_ULONG exp); - void __gmpz_sqrt(mpz_t rop, const mpz_t op); - void __gmpz_mod (mpz_t r, const mpz_t n, const mpz_t d); - void __gmpz_neg (mpz_t rop, const mpz_t op); - void __gmpz_abs (mpz_t rop, const mpz_t op); - void __gmpz_and (mpz_t rop, const mpz_t op1, const mpz_t op2); - void __gmpz_ior (mpz_t rop, const mpz_t op1, const mpz_t op2); - void __gmpz_clear (mpz_t x); - void __gmpz_tdiv_q_2exp (mpz_t q, const mpz_t n, mp_bitcnt_t b); - void __gmpz_fdiv_q (mpz_t q, const mpz_t n, const mpz_t d); - void __gmpz_mul_2exp (mpz_t rop, const mpz_t op1, mp_bitcnt_t op2); - int __gmpz_tstbit (const mpz_t op, mp_bitcnt_t bit_index); - int __gmpz_perfect_square_p (const mpz_t op); - int __gmpz_jacobi (const mpz_t a, const mpz_t b); - void __gmpz_gcd (mpz_t rop, const mpz_t op1, const mpz_t op2); - UNIX_ULONG __gmpz_gcd_ui (mpz_t rop, const mpz_t op1, - UNIX_ULONG op2); - void __gmpz_lcm (mpz_t rop, const mpz_t op1, const mpz_t op2); - int __gmpz_invert (mpz_t rop, const mpz_t op1, const mpz_t op2); - int __gmpz_divisible_p (const mpz_t n, const mpz_t d); - int __gmpz_divisible_ui_p (const mpz_t n, UNIX_ULONG d); - """ - -if sys.platform == "win32": - raise ImportError("Not using GMP on Windows") - -lib = load_lib("gmp", gmp_defs) -implementation = {"library": "gmp", "api": backend} - -if hasattr(lib, "__mpir_version"): - raise ImportError("MPIR library detected") - -# In order to create a function that returns a pointer to -# a new MPZ structure, we need to break the abstraction -# and know exactly what ffi backend we have -if implementation["api"] == "ctypes": - from ctypes import Structure, c_int, c_void_p, byref - - class _MPZ(Structure): - _fields_ = [('_mp_alloc', c_int), - ('_mp_size', c_int), - ('_mp_d', c_void_p)] - - def new_mpz(): - return byref(_MPZ()) - -else: - # We are using CFFI - from Crypto.Util._raw_api import ffi - - def new_mpz(): - return ffi.new("MPZ*") - - -# Lazy creation of GMP methods -class _GMP(object): - - def __getattr__(self, name): - if name.startswith("mpz_"): - func_name = "__gmpz_" + name[4:] - elif name.startswith("gmp_"): - func_name = "__gmp_" + name[4:] - else: - raise AttributeError("Attribute %s is invalid" % name) - func = getattr(lib, func_name) - setattr(self, name, func) - return func - - -_gmp = _GMP() - - -class IntegerGMP(IntegerBase): - """A fast, arbitrary precision integer""" - - _zero_mpz_p = new_mpz() - _gmp.mpz_init_set_ui(_zero_mpz_p, c_ulong(0)) - - def __init__(self, value): - """Initialize the integer to the given value.""" - - self._mpz_p = new_mpz() - self._initialized = False - - if isinstance(value, float): - raise ValueError("A floating point type is not a natural number") - - self._initialized = True - - if is_native_int(value): - _gmp.mpz_init(self._mpz_p) - result = _gmp.gmp_sscanf(tobytes(str(value)), b"%Zd", self._mpz_p) - if result != 1: - raise ValueError("Error converting '%d'" % value) - elif isinstance(value, IntegerGMP): - _gmp.mpz_init_set(self._mpz_p, value._mpz_p) - else: - raise NotImplementedError - - # Conversions - def __int__(self): - # buf will contain the integer encoded in decimal plus the trailing - # zero, and possibly the negative sign. - # dig10(x) < log10(x) + 1 = log2(x)/log2(10) + 1 < log2(x)/3 + 1 - buf_len = _gmp.mpz_sizeinbase(self._mpz_p, 2) // 3 + 3 - buf = create_string_buffer(buf_len) - - _gmp.gmp_snprintf(buf, c_size_t(buf_len), b"%Zd", self._mpz_p) - return int(get_c_string(buf)) - - def __str__(self): - return str(int(self)) - - def __repr__(self): - return "Integer(%s)" % str(self) - - # Only Python 2.x - def __hex__(self): - return hex(int(self)) - - # Only Python 3.x - def __index__(self): - return int(self) - - def to_bytes(self, block_size=0): - """Convert the number into a byte string. - - This method encodes the number in network order and prepends - as many zero bytes as required. It only works for non-negative - values. - - :Parameters: - block_size : integer - The exact size the output byte string must have. - If zero, the string has the minimal length. - :Returns: - A byte string. - :Raise ValueError: - If the value is negative or if ``block_size`` is - provided and the length of the byte string would exceed it. - """ - - if self < 0: - raise ValueError("Conversion only valid for non-negative numbers") - - buf_len = (_gmp.mpz_sizeinbase(self._mpz_p, 2) + 7) // 8 - if buf_len > block_size > 0: - raise ValueError("Number is too big to convert to byte string" - "of prescribed length") - buf = create_string_buffer(buf_len) - - _gmp.mpz_export( - buf, - null_pointer, # Ignore countp - 1, # Big endian - c_size_t(1), # Each word is 1 byte long - 0, # Endianess within a word - not relevant - c_size_t(0), # No nails - self._mpz_p) - - return b'\x00' * max(0, block_size - buf_len) + get_raw_buffer(buf) - - @staticmethod - def from_bytes(byte_string): - """Convert a byte string into a number. - - :Parameters: - byte_string : byte string - The input number, encoded in network order. - It can only be non-negative. - :Return: - The ``Integer`` object carrying the same value as the input. - """ - result = IntegerGMP(0) - _gmp.mpz_import( - result._mpz_p, - c_size_t(len(byte_string)), # Amount of words to read - 1, # Big endian - c_size_t(1), # Each word is 1 byte long - 0, # Endianess within a word - not relevant - c_size_t(0), # No nails - byte_string) - return result - - # Relations - def _apply_and_return(self, func, term): - if not isinstance(term, IntegerGMP): - term = IntegerGMP(term) - return func(self._mpz_p, term._mpz_p) - - def __eq__(self, term): - if not (isinstance(term, IntegerGMP) or is_native_int(term)): - return False - return self._apply_and_return(_gmp.mpz_cmp, term) == 0 - - def __ne__(self, term): - if not (isinstance(term, IntegerGMP) or is_native_int(term)): - return True - return self._apply_and_return(_gmp.mpz_cmp, term) != 0 - - def __lt__(self, term): - return self._apply_and_return(_gmp.mpz_cmp, term) < 0 - - def __le__(self, term): - return self._apply_and_return(_gmp.mpz_cmp, term) <= 0 - - def __gt__(self, term): - return self._apply_and_return(_gmp.mpz_cmp, term) > 0 - - def __ge__(self, term): - return self._apply_and_return(_gmp.mpz_cmp, term) >= 0 - - def __nonzero__(self): - return _gmp.mpz_cmp(self._mpz_p, self._zero_mpz_p) != 0 - __bool__ = __nonzero__ - - def is_negative(self): - return _gmp.mpz_cmp(self._mpz_p, self._zero_mpz_p) < 0 - - # Arithmetic operations - def __add__(self, term): - result = IntegerGMP(0) - if not isinstance(term, IntegerGMP): - try: - term = IntegerGMP(term) - except NotImplementedError: - return NotImplemented - _gmp.mpz_add(result._mpz_p, - self._mpz_p, - term._mpz_p) - return result - - def __sub__(self, term): - result = IntegerGMP(0) - if not isinstance(term, IntegerGMP): - try: - term = IntegerGMP(term) - except NotImplementedError: - return NotImplemented - _gmp.mpz_sub(result._mpz_p, - self._mpz_p, - term._mpz_p) - return result - - def __mul__(self, term): - result = IntegerGMP(0) - if not isinstance(term, IntegerGMP): - try: - term = IntegerGMP(term) - except NotImplementedError: - return NotImplemented - _gmp.mpz_mul(result._mpz_p, - self._mpz_p, - term._mpz_p) - return result - - def __floordiv__(self, divisor): - if not isinstance(divisor, IntegerGMP): - divisor = IntegerGMP(divisor) - if _gmp.mpz_cmp(divisor._mpz_p, - self._zero_mpz_p) == 0: - raise ZeroDivisionError("Division by zero") - result = IntegerGMP(0) - _gmp.mpz_fdiv_q(result._mpz_p, - self._mpz_p, - divisor._mpz_p) - return result - - def __mod__(self, divisor): - if not isinstance(divisor, IntegerGMP): - divisor = IntegerGMP(divisor) - comp = _gmp.mpz_cmp(divisor._mpz_p, - self._zero_mpz_p) - if comp == 0: - raise ZeroDivisionError("Division by zero") - if comp < 0: - raise ValueError("Modulus must be positive") - result = IntegerGMP(0) - _gmp.mpz_mod(result._mpz_p, - self._mpz_p, - divisor._mpz_p) - return result - - def inplace_pow(self, exponent, modulus=None): - - if modulus is None: - if exponent < 0: - raise ValueError("Exponent must not be negative") - - # Normal exponentiation - if exponent > 256: - raise ValueError("Exponent is too big") - _gmp.mpz_pow_ui(self._mpz_p, - self._mpz_p, # Base - c_ulong(int(exponent)) - ) - else: - # Modular exponentiation - if not isinstance(modulus, IntegerGMP): - modulus = IntegerGMP(modulus) - if not modulus: - raise ZeroDivisionError("Division by zero") - if modulus.is_negative(): - raise ValueError("Modulus must be positive") - if is_native_int(exponent): - if exponent < 0: - raise ValueError("Exponent must not be negative") - if exponent < 65536: - _gmp.mpz_powm_ui(self._mpz_p, - self._mpz_p, - c_ulong(exponent), - modulus._mpz_p) - return self - exponent = IntegerGMP(exponent) - elif exponent.is_negative(): - raise ValueError("Exponent must not be negative") - _gmp.mpz_powm(self._mpz_p, - self._mpz_p, - exponent._mpz_p, - modulus._mpz_p) - return self - - def __pow__(self, exponent, modulus=None): - result = IntegerGMP(self) - return result.inplace_pow(exponent, modulus) - - def __abs__(self): - result = IntegerGMP(0) - _gmp.mpz_abs(result._mpz_p, self._mpz_p) - return result - - def sqrt(self, modulus=None): - """Return the largest Integer that does not - exceed the square root""" - - if modulus is None: - if self < 0: - raise ValueError("Square root of negative value") - result = IntegerGMP(0) - _gmp.mpz_sqrt(result._mpz_p, - self._mpz_p) - else: - if modulus <= 0: - raise ValueError("Modulus must be positive") - modulus = int(modulus) - result = IntegerGMP(self._tonelli_shanks(int(self) % modulus, modulus)) - - return result - - def __iadd__(self, term): - if is_native_int(term): - if 0 <= term < 65536: - _gmp.mpz_add_ui(self._mpz_p, - self._mpz_p, - c_ulong(term)) - return self - if -65535 < term < 0: - _gmp.mpz_sub_ui(self._mpz_p, - self._mpz_p, - c_ulong(-term)) - return self - term = IntegerGMP(term) - _gmp.mpz_add(self._mpz_p, - self._mpz_p, - term._mpz_p) - return self - - def __isub__(self, term): - if is_native_int(term): - if 0 <= term < 65536: - _gmp.mpz_sub_ui(self._mpz_p, - self._mpz_p, - c_ulong(term)) - return self - if -65535 < term < 0: - _gmp.mpz_add_ui(self._mpz_p, - self._mpz_p, - c_ulong(-term)) - return self - term = IntegerGMP(term) - _gmp.mpz_sub(self._mpz_p, - self._mpz_p, - term._mpz_p) - return self - - def __imul__(self, term): - if is_native_int(term): - if 0 <= term < 65536: - _gmp.mpz_mul_ui(self._mpz_p, - self._mpz_p, - c_ulong(term)) - return self - if -65535 < term < 0: - _gmp.mpz_mul_ui(self._mpz_p, - self._mpz_p, - c_ulong(-term)) - _gmp.mpz_neg(self._mpz_p, self._mpz_p) - return self - term = IntegerGMP(term) - _gmp.mpz_mul(self._mpz_p, - self._mpz_p, - term._mpz_p) - return self - - def __imod__(self, divisor): - if not isinstance(divisor, IntegerGMP): - divisor = IntegerGMP(divisor) - comp = _gmp.mpz_cmp(divisor._mpz_p, - divisor._zero_mpz_p) - if comp == 0: - raise ZeroDivisionError("Division by zero") - if comp < 0: - raise ValueError("Modulus must be positive") - _gmp.mpz_mod(self._mpz_p, - self._mpz_p, - divisor._mpz_p) - return self - - # Boolean/bit operations - def __and__(self, term): - result = IntegerGMP(0) - if not isinstance(term, IntegerGMP): - term = IntegerGMP(term) - _gmp.mpz_and(result._mpz_p, - self._mpz_p, - term._mpz_p) - return result - - def __or__(self, term): - result = IntegerGMP(0) - if not isinstance(term, IntegerGMP): - term = IntegerGMP(term) - _gmp.mpz_ior(result._mpz_p, - self._mpz_p, - term._mpz_p) - return result - - def __rshift__(self, pos): - result = IntegerGMP(0) - if pos < 0: - raise ValueError("negative shift count") - if pos > 65536: - if self < 0: - return -1 - else: - return 0 - _gmp.mpz_tdiv_q_2exp(result._mpz_p, - self._mpz_p, - c_ulong(int(pos))) - return result - - def __irshift__(self, pos): - if pos < 0: - raise ValueError("negative shift count") - if pos > 65536: - if self < 0: - return -1 - else: - return 0 - _gmp.mpz_tdiv_q_2exp(self._mpz_p, - self._mpz_p, - c_ulong(int(pos))) - return self - - def __lshift__(self, pos): - result = IntegerGMP(0) - if not 0 <= pos < 65536: - raise ValueError("Incorrect shift count") - _gmp.mpz_mul_2exp(result._mpz_p, - self._mpz_p, - c_ulong(int(pos))) - return result - - def __ilshift__(self, pos): - if not 0 <= pos < 65536: - raise ValueError("Incorrect shift count") - _gmp.mpz_mul_2exp(self._mpz_p, - self._mpz_p, - c_ulong(int(pos))) - return self - - def get_bit(self, n): - """Return True if the n-th bit is set to 1. - Bit 0 is the least significant.""" - - if self < 0: - raise ValueError("no bit representation for negative values") - if n < 0: - raise ValueError("negative bit count") - if n > 65536: - return 0 - return bool(_gmp.mpz_tstbit(self._mpz_p, - c_ulong(int(n)))) - - # Extra - def is_odd(self): - return _gmp.mpz_tstbit(self._mpz_p, 0) == 1 - - def is_even(self): - return _gmp.mpz_tstbit(self._mpz_p, 0) == 0 - - def size_in_bits(self): - """Return the minimum number of bits that can encode the number.""" - - if self < 0: - raise ValueError("Conversion only valid for non-negative numbers") - return _gmp.mpz_sizeinbase(self._mpz_p, 2) - - def size_in_bytes(self): - """Return the minimum number of bytes that can encode the number.""" - return (self.size_in_bits() - 1) // 8 + 1 - - def is_perfect_square(self): - return _gmp.mpz_perfect_square_p(self._mpz_p) != 0 - - def fail_if_divisible_by(self, small_prime): - """Raise an exception if the small prime is a divisor.""" - - if is_native_int(small_prime): - if 0 < small_prime < 65536: - if _gmp.mpz_divisible_ui_p(self._mpz_p, - c_ulong(small_prime)): - raise ValueError("The value is composite") - return - small_prime = IntegerGMP(small_prime) - if _gmp.mpz_divisible_p(self._mpz_p, - small_prime._mpz_p): - raise ValueError("The value is composite") - - def multiply_accumulate(self, a, b): - """Increment the number by the product of a and b.""" - - if not isinstance(a, IntegerGMP): - a = IntegerGMP(a) - if is_native_int(b): - if 0 < b < 65536: - _gmp.mpz_addmul_ui(self._mpz_p, - a._mpz_p, - c_ulong(b)) - return self - if -65535 < b < 0: - _gmp.mpz_submul_ui(self._mpz_p, - a._mpz_p, - c_ulong(-b)) - return self - b = IntegerGMP(b) - _gmp.mpz_addmul(self._mpz_p, - a._mpz_p, - b._mpz_p) - return self - - def set(self, source): - """Set the Integer to have the given value""" - - if not isinstance(source, IntegerGMP): - source = IntegerGMP(source) - _gmp.mpz_set(self._mpz_p, - source._mpz_p) - return self - - def inplace_inverse(self, modulus): - """Compute the inverse of this number in the ring of - modulo integers. - - Raise an exception if no inverse exists. - """ - - if not isinstance(modulus, IntegerGMP): - modulus = IntegerGMP(modulus) - - comp = _gmp.mpz_cmp(modulus._mpz_p, - self._zero_mpz_p) - if comp == 0: - raise ZeroDivisionError("Modulus cannot be zero") - if comp < 0: - raise ValueError("Modulus must be positive") - - result = _gmp.mpz_invert(self._mpz_p, - self._mpz_p, - modulus._mpz_p) - if not result: - raise ValueError("No inverse value can be computed") - return self - - def inverse(self, modulus): - result = IntegerGMP(self) - result.inplace_inverse(modulus) - return result - - def gcd(self, term): - """Compute the greatest common denominator between this - number and another term.""" - - result = IntegerGMP(0) - if is_native_int(term): - if 0 < term < 65535: - _gmp.mpz_gcd_ui(result._mpz_p, - self._mpz_p, - c_ulong(term)) - return result - term = IntegerGMP(term) - _gmp.mpz_gcd(result._mpz_p, self._mpz_p, term._mpz_p) - return result - - def lcm(self, term): - """Compute the least common multiplier between this - number and another term.""" - - result = IntegerGMP(0) - if not isinstance(term, IntegerGMP): - term = IntegerGMP(term) - _gmp.mpz_lcm(result._mpz_p, self._mpz_p, term._mpz_p) - return result - - @staticmethod - def jacobi_symbol(a, n): - """Compute the Jacobi symbol""" - - if not isinstance(a, IntegerGMP): - a = IntegerGMP(a) - if not isinstance(n, IntegerGMP): - n = IntegerGMP(n) - if n <= 0 or n.is_even(): - raise ValueError("n must be positive even for the Jacobi symbol") - return _gmp.mpz_jacobi(a._mpz_p, n._mpz_p) - - # Clean-up - def __del__(self): - - try: - if self._mpz_p is not None: - if self._initialized: - _gmp.mpz_clear(self._mpz_p) - - self._mpz_p = None - except AttributeError: - pass diff --git a/Crypto/Math/_IntegerGMP.pyi b/Crypto/Math/_IntegerGMP.pyi deleted file mode 100644 index 2181b47..0000000 --- a/Crypto/Math/_IntegerGMP.pyi +++ /dev/null @@ -1,3 +0,0 @@ -from ._IntegerBase import IntegerBase -class IntegerGMP(IntegerBase): - pass diff --git a/Crypto/Math/_IntegerNative.py b/Crypto/Math/_IntegerNative.py deleted file mode 100644 index 07bf1c6..0000000 --- a/Crypto/Math/_IntegerNative.py +++ /dev/null @@ -1,380 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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 ._IntegerBase import IntegerBase - -from Crypto.Util.number import long_to_bytes, bytes_to_long - - -class IntegerNative(IntegerBase): - """A class to model a natural integer (including zero)""" - - def __init__(self, value): - if isinstance(value, float): - raise ValueError("A floating point type is not a natural number") - try: - self._value = value._value - except AttributeError: - self._value = value - - # Conversions - def __int__(self): - return self._value - - def __str__(self): - return str(int(self)) - - def __repr__(self): - return "Integer(%s)" % str(self) - - # Only Python 2.x - def __hex__(self): - return hex(self._value) - - # Only Python 3.x - def __index__(self): - return int(self._value) - - def to_bytes(self, block_size=0): - if self._value < 0: - raise ValueError("Conversion only valid for non-negative numbers") - result = long_to_bytes(self._value, block_size) - if len(result) > block_size > 0: - raise ValueError("Value too large to encode") - return result - - @classmethod - def from_bytes(cls, byte_string): - return cls(bytes_to_long(byte_string)) - - # Relations - def __eq__(self, term): - if term is None: - return False - return self._value == int(term) - - def __ne__(self, term): - return not self.__eq__(term) - - def __lt__(self, term): - return self._value < int(term) - - def __le__(self, term): - return self.__lt__(term) or self.__eq__(term) - - def __gt__(self, term): - return not self.__le__(term) - - def __ge__(self, term): - return not self.__lt__(term) - - def __nonzero__(self): - return self._value != 0 - __bool__ = __nonzero__ - - def is_negative(self): - return self._value < 0 - - # Arithmetic operations - def __add__(self, term): - try: - return self.__class__(self._value + int(term)) - except (ValueError, AttributeError, TypeError): - return NotImplemented - - def __sub__(self, term): - try: - return self.__class__(self._value - int(term)) - except (ValueError, AttributeError, TypeError): - return NotImplemented - - def __mul__(self, factor): - try: - return self.__class__(self._value * int(factor)) - except (ValueError, AttributeError, TypeError): - return NotImplemented - - def __floordiv__(self, divisor): - return self.__class__(self._value // int(divisor)) - - def __mod__(self, divisor): - divisor_value = int(divisor) - if divisor_value < 0: - raise ValueError("Modulus must be positive") - return self.__class__(self._value % divisor_value) - - def inplace_pow(self, exponent, modulus=None): - exp_value = int(exponent) - if exp_value < 0: - raise ValueError("Exponent must not be negative") - - if modulus is not None: - mod_value = int(modulus) - if mod_value < 0: - raise ValueError("Modulus must be positive") - if mod_value == 0: - raise ZeroDivisionError("Modulus cannot be zero") - else: - mod_value = None - self._value = pow(self._value, exp_value, mod_value) - return self - - def __pow__(self, exponent, modulus=None): - result = self.__class__(self) - return result.inplace_pow(exponent, modulus) - - def __abs__(self): - return abs(self._value) - - def sqrt(self, modulus=None): - - value = self._value - if modulus is None: - if value < 0: - raise ValueError("Square root of negative value") - # http://stackoverflow.com/questions/15390807/integer-square-root-in-python - - x = value - y = (x + 1) // 2 - while y < x: - x = y - y = (x + value // x) // 2 - result = x - else: - if modulus <= 0: - raise ValueError("Modulus must be positive") - result = self._tonelli_shanks(self % modulus, modulus) - - return self.__class__(result) - - def __iadd__(self, term): - self._value += int(term) - return self - - def __isub__(self, term): - self._value -= int(term) - return self - - def __imul__(self, term): - self._value *= int(term) - return self - - def __imod__(self, term): - modulus = int(term) - if modulus == 0: - raise ZeroDivisionError("Division by zero") - if modulus < 0: - raise ValueError("Modulus must be positive") - self._value %= modulus - return self - - # Boolean/bit operations - def __and__(self, term): - return self.__class__(self._value & int(term)) - - def __or__(self, term): - return self.__class__(self._value | int(term)) - - def __rshift__(self, pos): - try: - return self.__class__(self._value >> int(pos)) - except OverflowError: - if self._value >= 0: - return 0 - else: - return -1 - - def __irshift__(self, pos): - try: - self._value >>= int(pos) - except OverflowError: - if self._value >= 0: - return 0 - else: - return -1 - return self - - def __lshift__(self, pos): - try: - return self.__class__(self._value << int(pos)) - except OverflowError: - raise ValueError("Incorrect shift count") - - def __ilshift__(self, pos): - try: - self._value <<= int(pos) - except OverflowError: - raise ValueError("Incorrect shift count") - return self - - def get_bit(self, n): - if self._value < 0: - raise ValueError("no bit representation for negative values") - try: - try: - result = (self._value >> n._value) & 1 - if n._value < 0: - raise ValueError("negative bit count") - except AttributeError: - result = (self._value >> n) & 1 - if n < 0: - raise ValueError("negative bit count") - except OverflowError: - result = 0 - return result - - # Extra - def is_odd(self): - return (self._value & 1) == 1 - - def is_even(self): - return (self._value & 1) == 0 - - def size_in_bits(self): - - if self._value < 0: - raise ValueError("Conversion only valid for non-negative numbers") - - if self._value == 0: - return 1 - - bit_size = 0 - tmp = self._value - while tmp: - tmp >>= 1 - bit_size += 1 - - return bit_size - - def size_in_bytes(self): - return (self.size_in_bits() - 1) // 8 + 1 - - def is_perfect_square(self): - if self._value < 0: - return False - if self._value in (0, 1): - return True - - x = self._value // 2 - square_x = x ** 2 - - while square_x > self._value: - x = (square_x + self._value) // (2 * x) - square_x = x ** 2 - - return self._value == x ** 2 - - def fail_if_divisible_by(self, small_prime): - if (self._value % int(small_prime)) == 0: - raise ValueError("Value is composite") - - def multiply_accumulate(self, a, b): - self._value += int(a) * int(b) - return self - - def set(self, source): - self._value = int(source) - - def inplace_inverse(self, modulus): - modulus = int(modulus) - if modulus == 0: - raise ZeroDivisionError("Modulus cannot be zero") - if modulus < 0: - raise ValueError("Modulus cannot be negative") - r_p, r_n = self._value, modulus - s_p, s_n = 1, 0 - while r_n > 0: - q = r_p // r_n - r_p, r_n = r_n, r_p - q * r_n - s_p, s_n = s_n, s_p - q * s_n - if r_p != 1: - raise ValueError("No inverse value can be computed" + str(r_p)) - while s_p < 0: - s_p += modulus - self._value = s_p - return self - - def inverse(self, modulus): - result = self.__class__(self) - result.inplace_inverse(modulus) - return result - - def gcd(self, term): - r_p, r_n = abs(self._value), abs(int(term)) - while r_n > 0: - q = r_p // r_n - r_p, r_n = r_n, r_p - q * r_n - return self.__class__(r_p) - - def lcm(self, term): - term = int(term) - if self._value == 0 or term == 0: - return self.__class__(0) - return self.__class__(abs((self._value * term) // self.gcd(term)._value)) - - @staticmethod - def jacobi_symbol(a, n): - a = int(a) - n = int(n) - - if n <= 0: - raise ValueError("n must be a positive integer") - - if (n & 1) == 0: - raise ValueError("n must be even for the Jacobi symbol") - - # Step 1 - a = a % n - # Step 2 - if a == 1 or n == 1: - return 1 - # Step 3 - if a == 0: - return 0 - # Step 4 - e = 0 - a1 = a - while (a1 & 1) == 0: - a1 >>= 1 - e += 1 - # Step 5 - if (e & 1) == 0: - s = 1 - elif n % 8 in (1, 7): - s = 1 - else: - s = -1 - # Step 6 - if n % 4 == 3 and a1 % 4 == 3: - s = -s - # Step 7 - n1 = n % a1 - # Step 8 - return s * IntegerNative.jacobi_symbol(n1, a1) diff --git a/Crypto/Math/_IntegerNative.pyi b/Crypto/Math/_IntegerNative.pyi deleted file mode 100644 index 3f65a39..0000000 --- a/Crypto/Math/_IntegerNative.pyi +++ /dev/null @@ -1,3 +0,0 @@ -from ._IntegerBase import IntegerBase -class IntegerNative(IntegerBase): - pass diff --git a/Crypto/Math/__init__.py b/Crypto/Math/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/Crypto/Math/_modexp.abi3.so b/Crypto/Math/_modexp.abi3.so deleted file mode 100644 index 48715c0..0000000 Binary files a/Crypto/Math/_modexp.abi3.so and /dev/null differ diff --git a/Crypto/Protocol/KDF.py b/Crypto/Protocol/KDF.py deleted file mode 100644 index 1348265..0000000 --- a/Crypto/Protocol/KDF.py +++ /dev/null @@ -1,574 +0,0 @@ -# coding=utf-8 -# -# KDF.py : a collection of Key Derivation Functions -# -# Part of the Python Cryptography Toolkit -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -import re -import struct -from functools import reduce - -from Crypto.Util.py3compat import (tobytes, bord, _copy_bytes, iter_range, - tostr, bchr, bstr) - -from Crypto.Hash import SHA1, SHA256, HMAC, CMAC, BLAKE2s -from Crypto.Util.strxor import strxor -from Crypto.Random import get_random_bytes -from Crypto.Util.number import size as bit_size, long_to_bytes, bytes_to_long - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - create_string_buffer, - get_raw_buffer, c_size_t) - -_raw_salsa20_lib = load_pycryptodome_raw_lib("Crypto.Cipher._Salsa20", - """ - int Salsa20_8_core(const uint8_t *x, const uint8_t *y, - uint8_t *out); - """) - -_raw_scrypt_lib = load_pycryptodome_raw_lib("Crypto.Protocol._scrypt", - """ - typedef int (core_t)(const uint8_t [64], const uint8_t [64], uint8_t [64]); - int scryptROMix(const uint8_t *data_in, uint8_t *data_out, - size_t data_len, unsigned N, core_t *core); - """) - - -def PBKDF1(password, salt, dkLen, count=1000, hashAlgo=None): - """Derive one key from a password (or passphrase). - - This function performs key derivation according to an old version of - the PKCS#5 standard (v1.5) or `RFC2898 - `_. - - Args: - password (string): - The secret password to generate the key from. - salt (byte string): - An 8 byte string to use for better protection from dictionary attacks. - This value does not need to be kept secret, but it should be randomly - chosen for each derivation. - dkLen (integer): - The length of the desired key. The default is 16 bytes, suitable for - instance for :mod:`Crypto.Cipher.AES`. - count (integer): - The number of iterations to carry out. The recommendation is 1000 or - more. - hashAlgo (module): - The hash algorithm to use, as a module or an object from the :mod:`Crypto.Hash` package. - The digest length must be no shorter than ``dkLen``. - The default algorithm is :mod:`Crypto.Hash.SHA1`. - - Return: - A byte string of length ``dkLen`` that can be used as key. - """ - - if not hashAlgo: - hashAlgo = SHA1 - password = tobytes(password) - pHash = hashAlgo.new(password+salt) - digest = pHash.digest_size - if dkLen > digest: - raise TypeError("Selected hash algorithm has a too short digest (%d bytes)." % digest) - if len(salt) != 8: - raise ValueError("Salt is not 8 bytes long (%d bytes instead)." % len(salt)) - for i in iter_range(count-1): - pHash = pHash.new(pHash.digest()) - return pHash.digest()[:dkLen] - - -def PBKDF2(password, salt, dkLen=16, count=1000, prf=None, hmac_hash_module=None): - """Derive one or more keys from a password (or passphrase). - - This function performs key derivation according to the PKCS#5 standard (v2.0). - - Args: - password (string or byte string): - The secret password to generate the key from. - salt (string or byte string): - A (byte) string to use for better protection from dictionary attacks. - This value does not need to be kept secret, but it should be randomly - chosen for each derivation. It is recommended to use at least 16 bytes. - dkLen (integer): - The cumulative length of the keys to produce. - - Due to a flaw in the PBKDF2 design, you should not request more bytes - than the ``prf`` can output. For instance, ``dkLen`` should not exceed - 20 bytes in combination with ``HMAC-SHA1``. - count (integer): - The number of iterations to carry out. The higher the value, the slower - and the more secure the function becomes. - - You should find the maximum number of iterations that keeps the - key derivation still acceptable on the slowest hardware you must support. - - Although the default value is 1000, **it is recommended to use at least - 1000000 (1 million) iterations**. - prf (callable): - A pseudorandom function. It must be a function that returns a - pseudorandom byte string from two parameters: a secret and a salt. - The slower the algorithm, the more secure the derivation function. - If not specified, **HMAC-SHA1** is used. - hmac_hash_module (module): - A module from ``Crypto.Hash`` implementing a Merkle-Damgard cryptographic - hash, which PBKDF2 must use in combination with HMAC. - This parameter is mutually exclusive with ``prf``. - - Return: - A byte string of length ``dkLen`` that can be used as key material. - If you want multiple keys, just break up this string into segments of the desired length. - """ - - password = tobytes(password) - salt = tobytes(salt) - - if prf and hmac_hash_module: - raise ValueError("'prf' and 'hmac_hash_module' are mutually exlusive") - - if prf is None and hmac_hash_module is None: - hmac_hash_module = SHA1 - - if prf or not hasattr(hmac_hash_module, "_pbkdf2_hmac_assist"): - # Generic (and slow) implementation - - if prf is None: - prf = lambda p,s: HMAC.new(p, s, hmac_hash_module).digest() - - def link(s): - s[0], s[1] = s[1], prf(password, s[1]) - return s[0] - - key = b'' - i = 1 - while len(key) < dkLen: - s = [ prf(password, salt + struct.pack(">I", i)) ] * 2 - key += reduce(strxor, (link(s) for j in range(count)) ) - i += 1 - - else: - # Optimized implementation - key = b'' - i = 1 - while len(key)I", i)).digest() - key += base._pbkdf2_hmac_assist(first_digest, count) - i += 1 - - return key[:dkLen] - - -class _S2V(object): - """String-to-vector PRF as defined in `RFC5297`_. - - This class implements a pseudorandom function family - based on CMAC that takes as input a vector of strings. - - .. _RFC5297: http://tools.ietf.org/html/rfc5297 - """ - - def __init__(self, key, ciphermod, cipher_params=None): - """Initialize the S2V PRF. - - :Parameters: - key : byte string - A secret that can be used as key for CMACs - based on ciphers from ``ciphermod``. - ciphermod : module - A block cipher module from `Crypto.Cipher`. - cipher_params : dictionary - A set of extra parameters to use to create a cipher instance. - """ - - self._key = _copy_bytes(None, None, key) - self._ciphermod = ciphermod - self._last_string = self._cache = b'\x00' * ciphermod.block_size - - # Max number of update() call we can process - self._n_updates = ciphermod.block_size * 8 - 1 - - if cipher_params is None: - self._cipher_params = {} - else: - self._cipher_params = dict(cipher_params) - - @staticmethod - def new(key, ciphermod): - """Create a new S2V PRF. - - :Parameters: - key : byte string - A secret that can be used as key for CMACs - based on ciphers from ``ciphermod``. - ciphermod : module - A block cipher module from `Crypto.Cipher`. - """ - return _S2V(key, ciphermod) - - def _double(self, bs): - doubled = bytes_to_long(bs)<<1 - if bord(bs[0]) & 0x80: - doubled ^= 0x87 - return long_to_bytes(doubled, len(bs))[-len(bs):] - - def update(self, item): - """Pass the next component of the vector. - - The maximum number of components you can pass is equal to the block - length of the cipher (in bits) minus 1. - - :Parameters: - item : byte string - The next component of the vector. - :Raise TypeError: when the limit on the number of components has been reached. - """ - - if self._n_updates == 0: - raise TypeError("Too many components passed to S2V") - self._n_updates -= 1 - - mac = CMAC.new(self._key, - msg=self._last_string, - ciphermod=self._ciphermod, - cipher_params=self._cipher_params) - self._cache = strxor(self._double(self._cache), mac.digest()) - self._last_string = _copy_bytes(None, None, item) - - def derive(self): - """"Derive a secret from the vector of components. - - :Return: a byte string, as long as the block length of the cipher. - """ - - if len(self._last_string) >= 16: - # xorend - final = self._last_string[:-16] + strxor(self._last_string[-16:], self._cache) - else: - # zero-pad & xor - padded = (self._last_string + b'\x80' + b'\x00' * 15)[:16] - final = strxor(padded, self._double(self._cache)) - mac = CMAC.new(self._key, - msg=final, - ciphermod=self._ciphermod, - cipher_params=self._cipher_params) - return mac.digest() - - -def HKDF(master, key_len, salt, hashmod, num_keys=1, context=None): - """Derive one or more keys from a master secret using - the HMAC-based KDF defined in RFC5869_. - - Args: - master (byte string): - The unguessable value used by the KDF to generate the other keys. - It must be a high-entropy secret, though not necessarily uniform. - It must not be a password. - salt (byte string): - A non-secret, reusable value that strengthens the randomness - extraction step. - Ideally, it is as long as the digest size of the chosen hash. - If empty, a string of zeroes in used. - key_len (integer): - The length in bytes of every derived key. - hashmod (module): - A cryptographic hash algorithm from :mod:`Crypto.Hash`. - :mod:`Crypto.Hash.SHA512` is a good choice. - num_keys (integer): - The number of keys to derive. Every key is :data:`key_len` bytes long. - The maximum cumulative length of all keys is - 255 times the digest size. - context (byte string): - Optional identifier describing what the keys are used for. - - Return: - A byte string or a tuple of byte strings. - - .. _RFC5869: http://tools.ietf.org/html/rfc5869 - """ - - output_len = key_len * num_keys - if output_len > (255 * hashmod.digest_size): - raise ValueError("Too much secret data to derive") - if not salt: - salt = b'\x00' * hashmod.digest_size - if context is None: - context = b"" - - # Step 1: extract - hmac = HMAC.new(salt, master, digestmod=hashmod) - prk = hmac.digest() - - # Step 2: expand - t = [ b"" ] - n = 1 - tlen = 0 - while tlen < output_len: - hmac = HMAC.new(prk, t[-1] + context + struct.pack('B', n), digestmod=hashmod) - t.append(hmac.digest()) - tlen += hashmod.digest_size - n += 1 - derived_output = b"".join(t) - if num_keys == 1: - return derived_output[:key_len] - kol = [derived_output[idx:idx + key_len] - for idx in iter_range(0, output_len, key_len)] - return list(kol[:num_keys]) - - - -def scrypt(password, salt, key_len, N, r, p, num_keys=1): - """Derive one or more keys from a passphrase. - - Args: - password (string): - The secret pass phrase to generate the keys from. - salt (string): - A string to use for better protection from dictionary attacks. - This value does not need to be kept secret, - but it should be randomly chosen for each derivation. - It is recommended to be at least 16 bytes long. - key_len (integer): - The length in bytes of every derived key. - N (integer): - CPU/Memory cost parameter. It must be a power of 2 and less - than :math:`2^{32}`. - r (integer): - Block size parameter. - p (integer): - Parallelization parameter. - It must be no greater than :math:`(2^{32}-1)/(4r)`. - num_keys (integer): - The number of keys to derive. Every key is :data:`key_len` bytes long. - By default, only 1 key is generated. - The maximum cumulative length of all keys is :math:`(2^{32}-1)*32` - (that is, 128TB). - - A good choice of parameters *(N, r , p)* was suggested - by Colin Percival in his `presentation in 2009`__: - - - *( 2¹⁴, 8, 1 )* for interactive logins (≤100ms) - - *( 2²⁰, 8, 1 )* for file encryption (≤5s) - - Return: - A byte string or a tuple of byte strings. - - .. __: http://www.tarsnap.com/scrypt/scrypt-slides.pdf - """ - - if 2 ** (bit_size(N) - 1) != N: - raise ValueError("N must be a power of 2") - if N >= 2 ** 32: - raise ValueError("N is too big") - if p > ((2 ** 32 - 1) * 32) // (128 * r): - raise ValueError("p or r are too big") - - prf_hmac_sha256 = lambda p, s: HMAC.new(p, s, SHA256).digest() - - stage_1 = PBKDF2(password, salt, p * 128 * r, 1, prf=prf_hmac_sha256) - - scryptROMix = _raw_scrypt_lib.scryptROMix - core = _raw_salsa20_lib.Salsa20_8_core - - # Parallelize into p flows - data_out = [] - for flow in iter_range(p): - idx = flow * 128 * r - buffer_out = create_string_buffer(128 * r) - result = scryptROMix(stage_1[idx : idx + 128 * r], - buffer_out, - c_size_t(128 * r), - N, - core) - if result: - raise ValueError("Error %X while running scrypt" % result) - data_out += [ get_raw_buffer(buffer_out) ] - - dk = PBKDF2(password, - b"".join(data_out), - key_len * num_keys, 1, - prf=prf_hmac_sha256) - - if num_keys == 1: - return dk - - kol = [dk[idx:idx + key_len] - for idx in iter_range(0, key_len * num_keys, key_len)] - return kol - - -def _bcrypt_encode(data): - s = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - - bits = [] - for c in data: - bits_c = bin(bord(c))[2:].zfill(8) - bits.append(bstr(bits_c)) - bits = b"".join(bits) - - bits6 = [ bits[idx:idx+6] for idx in range(0, len(bits), 6) ] - - result = [] - for g in bits6[:-1]: - idx = int(g, 2) - result.append(s[idx]) - - g = bits6[-1] - idx = int(g, 2) << (6 - len(g)) - result.append(s[idx]) - result = "".join(result) - - return tobytes(result) - - -def _bcrypt_decode(data): - s = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - - bits = [] - for c in tostr(data): - idx = s.find(c) - bits6 = bin(idx)[2:].zfill(6) - bits.append(bits6) - bits = "".join(bits) - - modulo4 = len(data) % 4 - if modulo4 == 1: - raise ValueError("Incorrect length") - elif modulo4 == 2: - bits = bits[:-4] - elif modulo4 == 3: - bits = bits[:-2] - - bits8 = [ bits[idx:idx+8] for idx in range(0, len(bits), 8) ] - - result = [] - for g in bits8: - result.append(bchr(int(g, 2))) - result = b"".join(result) - - return result - - -def _bcrypt_hash(password, cost, salt, constant, invert): - from Crypto.Cipher import _EKSBlowfish - - if len(password) > 72: - raise ValueError("The password is too long. It must be 72 bytes at most.") - - if not (4 <= cost <= 31): - raise ValueError("bcrypt cost factor must be in the range 4..31") - - cipher = _EKSBlowfish.new(password, _EKSBlowfish.MODE_ECB, salt, cost, invert) - ctext = constant - for _ in range(64): - ctext = cipher.encrypt(ctext) - return ctext - - -def bcrypt(password, cost, salt=None): - """Hash a password into a key, using the OpenBSD bcrypt protocol. - - Args: - password (byte string or string): - The secret password or pass phrase. - It must be at most 72 bytes long. - It must not contain the zero byte. - Unicode strings will be encoded as UTF-8. - cost (integer): - The exponential factor that makes it slower to compute the hash. - It must be in the range 4 to 31. - A value of at least 12 is recommended. - salt (byte string): - Optional. Random byte string to thwarts dictionary and rainbow table - attacks. It must be 16 bytes long. - If not passed, a random value is generated. - - Return (byte string): - The bcrypt hash - - Raises: - ValueError: if password is longer than 72 bytes or if it contains the zero byte - - """ - - password = tobytes(password, "utf-8") - - if password.find(bchr(0)[0]) != -1: - raise ValueError("The password contains the zero byte") - - if len(password) < 72: - password += b"\x00" - - if salt is None: - salt = get_random_bytes(16) - if len(salt) != 16: - raise ValueError("bcrypt salt must be 16 bytes long") - - ctext = _bcrypt_hash(password, cost, salt, b"OrpheanBeholderScryDoubt", True) - - cost_enc = b"$" + bstr(str(cost).zfill(2)) - salt_enc = b"$" + _bcrypt_encode(salt) - hash_enc = _bcrypt_encode(ctext[:-1]) # only use 23 bytes, not 24 - return b"$2a" + cost_enc + salt_enc + hash_enc - - -def bcrypt_check(password, bcrypt_hash): - """Verify if the provided password matches the given bcrypt hash. - - Args: - password (byte string or string): - The secret password or pass phrase to test. - It must be at most 72 bytes long. - It must not contain the zero byte. - Unicode strings will be encoded as UTF-8. - bcrypt_hash (byte string, bytearray): - The reference bcrypt hash the password needs to be checked against. - - Raises: - ValueError: if the password does not match - """ - - bcrypt_hash = tobytes(bcrypt_hash) - - if len(bcrypt_hash) != 60: - raise ValueError("Incorrect length of the bcrypt hash: %d bytes instead of 60" % len(bcrypt_hash)) - - if bcrypt_hash[:4] != b'$2a$': - raise ValueError("Unsupported prefix") - - p = re.compile(br'\$2a\$([0-9][0-9])\$([A-Za-z0-9./]{22,22})([A-Za-z0-9./]{31,31})') - r = p.match(bcrypt_hash) - if not r: - raise ValueError("Incorrect bcrypt hash format") - - cost = int(r.group(1)) - if not (4 <= cost <= 31): - raise ValueError("Incorrect cost") - - salt = _bcrypt_decode(r.group(2)) - - bcrypt_hash2 = bcrypt(password, cost, salt) - - secret = get_random_bytes(16) - - mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=bcrypt_hash).digest() - mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=bcrypt_hash2).digest() - if mac1 != mac2: - raise ValueError("Incorrect bcrypt hash") diff --git a/Crypto/Protocol/KDF.pyi b/Crypto/Protocol/KDF.pyi deleted file mode 100644 index fb004bf..0000000 --- a/Crypto/Protocol/KDF.pyi +++ /dev/null @@ -1,24 +0,0 @@ -from types import ModuleType -from typing import Optional, Callable, Tuple, Union, Dict, Any - -RNG = Callable[[int], bytes] - -def PBKDF1(password: str, salt: bytes, dkLen: int, count: Optional[int]=1000, hashAlgo: Optional[ModuleType]=None) -> bytes: ... -def PBKDF2(password: str, salt: bytes, dkLen: Optional[int]=16, count: Optional[int]=1000, prf: Optional[RNG]=None, hmac_hash_module: Optional[ModuleType]=None) -> bytes: ... - -class _S2V(object): - def __init__(self, key: bytes, ciphermod: ModuleType, cipher_params: Optional[Dict[Any, Any]]=None) -> None: ... - - @staticmethod - def new(key: bytes, ciphermod: ModuleType) -> None: ... - def update(self, item: bytes) -> None: ... - def derive(self) -> bytes: ... - -def HKDF(master: bytes, key_len: int, salt: bytes, hashmod: ModuleType, num_keys: Optional[int]=1, context: Optional[bytes]=None) -> Union[bytes, Tuple[bytes, ...]]: ... - -def scrypt(password: str, salt: str, key_len: int, N: int, r: int, p: int, num_keys: Optional[int]=1) -> Union[bytes, Tuple[bytes, ...]]: ... - -def _bcrypt_decode(data: bytes) -> bytes: ... -def _bcrypt_hash(password:bytes , cost: int, salt: bytes, constant:bytes, invert:bool) -> bytes: ... -def bcrypt(password: Union[bytes, str], cost: int, salt: Optional[bytes]=None) -> bytes: ... -def bcrypt_check(password: Union[bytes, str], bcrypt_hash: Union[bytes, bytearray, str]) -> None: ... diff --git a/Crypto/Protocol/SecretSharing.py b/Crypto/Protocol/SecretSharing.py deleted file mode 100644 index a757e7c..0000000 --- a/Crypto/Protocol/SecretSharing.py +++ /dev/null @@ -1,278 +0,0 @@ -# -# SecretSharing.py : distribute a secret amongst a group of participants -# -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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 Crypto.Util.py3compat import is_native_int -from Crypto.Util import number -from Crypto.Util.number import long_to_bytes, bytes_to_long -from Crypto.Random import get_random_bytes as rng - - -def _mult_gf2(f1, f2): - """Multiply two polynomials in GF(2)""" - - # Ensure f2 is the smallest - if f2 > f1: - f1, f2 = f2, f1 - z = 0 - while f2: - if f2 & 1: - z ^= f1 - f1 <<= 1 - f2 >>= 1 - return z - - -def _div_gf2(a, b): - """ - Compute division of polynomials over GF(2). - Given a and b, it finds two polynomials q and r such that: - - a = b*q + r with deg(r)= d: - s = 1 << (deg(r) - d) - q ^= s - r ^= _mult_gf2(b, s) - return (q, r) - - -class _Element(object): - """Element of GF(2^128) field""" - - # The irreducible polynomial defining this field is 1+x+x^2+x^7+x^128 - irr_poly = 1 + 2 + 4 + 128 + 2 ** 128 - - def __init__(self, encoded_value): - """Initialize the element to a certain value. - - The value passed as parameter is internally encoded as - a 128-bit integer, where each bit represents a polynomial - coefficient. The LSB is the constant coefficient. - """ - - if is_native_int(encoded_value): - self._value = encoded_value - elif len(encoded_value) == 16: - self._value = bytes_to_long(encoded_value) - else: - raise ValueError("The encoded value must be an integer or a 16 byte string") - - def __eq__(self, other): - return self._value == other._value - - def __int__(self): - """Return the field element, encoded as a 128-bit integer.""" - return self._value - - def encode(self): - """Return the field element, encoded as a 16 byte string.""" - return long_to_bytes(self._value, 16) - - def __mul__(self, factor): - - f1 = self._value - f2 = factor._value - - # Make sure that f2 is the smallest, to speed up the loop - if f2 > f1: - f1, f2 = f2, f1 - - if self.irr_poly in (f1, f2): - return _Element(0) - - mask1 = 2 ** 128 - v, z = f1, 0 - while f2: - # if f2 ^ 1: z ^= v - mask2 = int(bin(f2 & 1)[2:] * 128, base=2) - z = (mask2 & (z ^ v)) | ((mask1 - mask2 - 1) & z) - v <<= 1 - # if v & mask1: v ^= self.irr_poly - mask3 = int(bin((v >> 128) & 1)[2:] * 128, base=2) - v = (mask3 & (v ^ self.irr_poly)) | ((mask1 - mask3 - 1) & v) - f2 >>= 1 - return _Element(z) - - def __add__(self, term): - return _Element(self._value ^ term._value) - - def inverse(self): - """Return the inverse of this element in GF(2^128).""" - - # We use the Extended GCD algorithm - # http://en.wikipedia.org/wiki/Polynomial_greatest_common_divisor - - if self._value == 0: - raise ValueError("Inversion of zero") - - r0, r1 = self._value, self.irr_poly - s0, s1 = 1, 0 - while r1 > 0: - q = _div_gf2(r0, r1)[0] - r0, r1 = r1, r0 ^ _mult_gf2(q, r1) - s0, s1 = s1, s0 ^ _mult_gf2(q, s1) - return _Element(s0) - - def __pow__(self, exponent): - result = _Element(self._value) - for _ in range(exponent - 1): - result = result * self - return result - - -class Shamir(object): - """Shamir's secret sharing scheme. - - A secret is split into ``n`` shares, and it is sufficient to collect - ``k`` of them to reconstruct the secret. - """ - - @staticmethod - def split(k, n, secret, ssss=False): - """Split a secret into ``n`` shares. - - The secret can be reconstructed later using just ``k`` shares - out of the original ``n``. - Each share must be kept confidential to the person it was - assigned to. - - Each share is associated to an index (starting from 1). - - Args: - k (integer): - The sufficient number of shares to reconstruct the secret (``k < n``). - n (integer): - The number of shares that this method will create. - secret (byte string): - A byte string of 16 bytes (e.g. the AES 128 key). - ssss (bool): - If ``True``, the shares can be used with the ``ssss`` utility. - Default: ``False``. - - Return (tuples): - ``n`` tuples. A tuple is meant for each participant and it contains two items: - - 1. the unique index (an integer) - 2. the share (a byte string, 16 bytes) - """ - - # - # We create a polynomial with random coefficients in GF(2^128): - # - # p(x) = \sum_{i=0}^{k-1} c_i * x^i - # - # c_0 is the encoded secret - # - - coeffs = [_Element(rng(16)) for i in range(k - 1)] - coeffs.append(_Element(secret)) - - # Each share is y_i = p(x_i) where x_i is the public index - # associated to each of the n users. - - def make_share(user, coeffs, ssss): - idx = _Element(user) - share = _Element(0) - for coeff in coeffs: - share = idx * share + coeff - if ssss: - share += _Element(user) ** len(coeffs) - return share.encode() - - return [(i, make_share(i, coeffs, ssss)) for i in range(1, n + 1)] - - @staticmethod - def combine(shares, ssss=False): - """Recombine a secret, if enough shares are presented. - - Args: - shares (tuples): - The *k* tuples, each containin the index (an integer) and - the share (a byte string, 16 bytes long) that were assigned to - a participant. - ssss (bool): - If ``True``, the shares were produced by the ``ssss`` utility. - Default: ``False``. - - Return: - The original secret, as a byte string (16 bytes long). - """ - - # - # Given k points (x,y), the interpolation polynomial of degree k-1 is: - # - # L(x) = \sum_{j=0}^{k-1} y_i * l_j(x) - # - # where: - # - # l_j(x) = \prod_{ \overset{0 \le m \le k-1}{m \ne j} } - # \frac{x - x_m}{x_j - x_m} - # - # However, in this case we are purely interested in the constant - # coefficient of L(x). - # - - k = len(shares) - - gf_shares = [] - for x in shares: - idx = _Element(x[0]) - value = _Element(x[1]) - if any(y[0] == idx for y in gf_shares): - raise ValueError("Duplicate share") - if ssss: - value += idx ** k - gf_shares.append((idx, value)) - - result = _Element(0) - for j in range(k): - x_j, y_j = gf_shares[j] - - numerator = _Element(1) - denominator = _Element(1) - - for m in range(k): - x_m = gf_shares[m][0] - if m != j: - numerator *= x_m - denominator *= x_j + x_m - result += y_j * numerator * denominator.inverse() - return result.encode() diff --git a/Crypto/Protocol/SecretSharing.pyi b/Crypto/Protocol/SecretSharing.pyi deleted file mode 100644 index 5952c99..0000000 --- a/Crypto/Protocol/SecretSharing.pyi +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Union, List, Tuple, Optional - -def _mult_gf2(f1: int, f2: int) -> int : ... -def _div_gf2(a: int, b: int) -> int : ... - -class _Element(object): - irr_poly: int - def __init__(self, encoded_value: Union[int, bytes]) -> None: ... - def __eq__(self, other) -> bool: ... - def __int__(self) -> int: ... - def encode(self) -> bytes: ... - def __mul__(self, factor: int) -> _Element: ... - def __add__(self, term: _Element) -> _Element: ... - def inverse(self) -> _Element: ... - def __pow__(self, exponent) -> _Element: ... - -class Shamir(object): - @staticmethod - def split(k: int, n: int, secret: bytes, ssss: Optional[bool]) -> List[Tuple[int, bytes]]: ... - @staticmethod - def combine(shares: List[Tuple[int, bytes]], ssss: Optional[bool]) -> bytes: ... - diff --git a/Crypto/Protocol/__init__.py b/Crypto/Protocol/__init__.py deleted file mode 100644 index efdf034..0000000 --- a/Crypto/Protocol/__init__.py +++ /dev/null @@ -1,31 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -__all__ = ['KDF', 'SecretSharing'] diff --git a/Crypto/Protocol/__init__.pyi b/Crypto/Protocol/__init__.pyi deleted file mode 100644 index 377ed90..0000000 --- a/Crypto/Protocol/__init__.pyi +++ /dev/null @@ -1 +0,0 @@ -__all__ = ['KDF.pyi', 'SecretSharing.pyi'] diff --git a/Crypto/Protocol/__pycache__/KDF.cpython-36.pyc b/Crypto/Protocol/__pycache__/KDF.cpython-36.pyc deleted file mode 100644 index b48e0b0..0000000 Binary files a/Crypto/Protocol/__pycache__/KDF.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Protocol/__pycache__/__init__.cpython-36.pyc b/Crypto/Protocol/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index 8b4c04b..0000000 Binary files a/Crypto/Protocol/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Protocol/_scrypt.abi3.so b/Crypto/Protocol/_scrypt.abi3.so deleted file mode 100644 index 129f28c..0000000 Binary files a/Crypto/Protocol/_scrypt.abi3.so and /dev/null differ diff --git a/Crypto/PublicKey/DSA.py b/Crypto/PublicKey/DSA.py deleted file mode 100644 index 8d603a9..0000000 --- a/Crypto/PublicKey/DSA.py +++ /dev/null @@ -1,682 +0,0 @@ -# -*- coding: utf-8 -*- -# -# PublicKey/DSA.py : DSA signature primitive -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# 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. -# =================================================================== - -__all__ = ['generate', 'construct', 'DsaKey', 'import_key' ] - -import binascii -import struct -import itertools - -from Crypto.Util.py3compat import bchr, bord, tobytes, tostr, iter_range - -from Crypto import Random -from Crypto.IO import PKCS8, PEM -from Crypto.Hash import SHA256 -from Crypto.Util.asn1 import ( - DerObject, DerSequence, - DerInteger, DerObjectId, - DerBitString, - ) - -from Crypto.Math.Numbers import Integer -from Crypto.Math.Primality import (test_probable_prime, COMPOSITE, - PROBABLY_PRIME) - -from Crypto.PublicKey import (_expand_subject_public_key_info, - _create_subject_public_key_info, - _extract_subject_public_key_info) - -# ; The following ASN.1 types are relevant for DSA -# -# SubjectPublicKeyInfo ::= SEQUENCE { -# algorithm AlgorithmIdentifier, -# subjectPublicKey BIT STRING -# } -# -# id-dsa ID ::= { iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 1 } -# -# ; See RFC3279 -# Dss-Parms ::= SEQUENCE { -# p INTEGER, -# q INTEGER, -# g INTEGER -# } -# -# DSAPublicKey ::= INTEGER -# -# DSSPrivatKey_OpenSSL ::= SEQUENCE -# version INTEGER, -# p INTEGER, -# q INTEGER, -# g INTEGER, -# y INTEGER, -# x INTEGER -# } -# - -class DsaKey(object): - r"""Class defining an actual DSA key. - Do not instantiate directly. - Use :func:`generate`, :func:`construct` or :func:`import_key` instead. - - :ivar p: DSA modulus - :vartype p: integer - - :ivar q: Order of the subgroup - :vartype q: integer - - :ivar g: Generator - :vartype g: integer - - :ivar y: Public key - :vartype y: integer - - :ivar x: Private key - :vartype x: integer - - :undocumented: exportKey, publickey - """ - - _keydata = ['y', 'g', 'p', 'q', 'x'] - - def __init__(self, key_dict): - input_set = set(key_dict.keys()) - public_set = set(('y' , 'g', 'p', 'q')) - if not public_set.issubset(input_set): - raise ValueError("Some DSA components are missing = %s" % - str(public_set - input_set)) - extra_set = input_set - public_set - if extra_set and extra_set != set(('x',)): - raise ValueError("Unknown DSA components = %s" % - str(extra_set - set(('x',)))) - self._key = dict(key_dict) - - def _sign(self, m, k): - if not self.has_private(): - raise TypeError("DSA public key cannot be used for signing") - if not (1 < k < self.q): - raise ValueError("k is not between 2 and q-1") - - x, q, p, g = [self._key[comp] for comp in ['x', 'q', 'p', 'g']] - - blind_factor = Integer.random_range(min_inclusive=1, - max_exclusive=q) - inv_blind_k = (blind_factor * k).inverse(q) - blind_x = x * blind_factor - - r = pow(g, k, p) % q # r = (g**k mod p) mod q - s = (inv_blind_k * (blind_factor * m + blind_x * r)) % q - return map(int, (r, s)) - - def _verify(self, m, sig): - r, s = sig - y, q, p, g = [self._key[comp] for comp in ['y', 'q', 'p', 'g']] - if not (0 < r < q) or not (0 < s < q): - return False - w = Integer(s).inverse(q) - u1 = (w * m) % q - u2 = (w * r) % q - v = (pow(g, u1, p) * pow(y, u2, p) % p) % q - return v == r - - def has_private(self): - """Whether this is a DSA private key""" - - return 'x' in self._key - - def can_encrypt(self): # legacy - return False - - def can_sign(self): # legacy - return True - - def public_key(self): - """A matching DSA public key. - - Returns: - a new :class:`DsaKey` object - """ - - public_components = dict((k, self._key[k]) for k in ('y', 'g', 'p', 'q')) - return DsaKey(public_components) - - def __eq__(self, other): - if bool(self.has_private()) != bool(other.has_private()): - return False - - result = True - for comp in self._keydata: - result = result and (getattr(self._key, comp, None) == - getattr(other._key, comp, None)) - return result - - def __ne__(self, other): - return not self.__eq__(other) - - def __getstate__(self): - # DSA key is not pickable - from pickle import PicklingError - raise PicklingError - - def domain(self): - """The DSA domain parameters. - - Returns - tuple : (p,q,g) - """ - - return [int(self._key[comp]) for comp in ('p', 'q', 'g')] - - def __repr__(self): - attrs = [] - for k in self._keydata: - if k == 'p': - bits = Integer(self.p).size_in_bits() - attrs.append("p(%d)" % (bits,)) - elif hasattr(self, k): - attrs.append(k) - if self.has_private(): - attrs.append("private") - # PY3K: This is meant to be text, do not change to bytes (data) - return "<%s @0x%x %s>" % (self.__class__.__name__, id(self), ",".join(attrs)) - - def __getattr__(self, item): - try: - return int(self._key[item]) - except KeyError: - raise AttributeError(item) - - def export_key(self, format='PEM', pkcs8=None, passphrase=None, - protection=None, randfunc=None): - """Export this DSA key. - - Args: - format (string): - The encoding for the output: - - - *'PEM'* (default). ASCII as per `RFC1421`_/ `RFC1423`_. - - *'DER'*. Binary ASN.1 encoding. - - *'OpenSSH'*. ASCII one-liner as per `RFC4253`_. - Only suitable for public keys, not for private keys. - - passphrase (string): - *Private keys only*. The pass phrase to protect the output. - - pkcs8 (boolean): - *Private keys only*. If ``True`` (default), the key is encoded - with `PKCS#8`_. If ``False``, it is encoded in the custom - OpenSSL/OpenSSH container. - - protection (string): - *Only in combination with a pass phrase*. - The encryption scheme to use to protect the output. - - If :data:`pkcs8` takes value ``True``, this is the PKCS#8 - algorithm to use for deriving the secret and encrypting - the private DSA key. - For a complete list of algorithms, see :mod:`Crypto.IO.PKCS8`. - The default is *PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC*. - - If :data:`pkcs8` is ``False``, the obsolete PEM encryption scheme is - used. It is based on MD5 for key derivation, and Triple DES for - encryption. Parameter :data:`protection` is then ignored. - - The combination ``format='DER'`` and ``pkcs8=False`` is not allowed - if a passphrase is present. - - randfunc (callable): - A function that returns random bytes. - By default it is :func:`Crypto.Random.get_random_bytes`. - - Returns: - byte string : the encoded key - - Raises: - ValueError : when the format is unknown or when you try to encrypt a private - key with *DER* format and OpenSSL/OpenSSH. - - .. warning:: - If you don't provide a pass phrase, the private key will be - exported in the clear! - - .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt - .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt - .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt - .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt - """ - - if passphrase is not None: - passphrase = tobytes(passphrase) - - if randfunc is None: - randfunc = Random.get_random_bytes - - if format == 'OpenSSH': - tup1 = [self._key[x].to_bytes() for x in ('p', 'q', 'g', 'y')] - - def func(x): - if (bord(x[0]) & 0x80): - return bchr(0) + x - else: - return x - - tup2 = [func(x) for x in tup1] - keyparts = [b'ssh-dss'] + tup2 - keystring = b''.join( - [struct.pack(">I", len(kp)) + kp for kp in keyparts] - ) - return b'ssh-dss ' + binascii.b2a_base64(keystring)[:-1] - - # DER format is always used, even in case of PEM, which simply - # encodes it into BASE64. - params = DerSequence([self.p, self.q, self.g]) - if self.has_private(): - if pkcs8 is None: - pkcs8 = True - if pkcs8: - if not protection: - protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC' - private_key = DerInteger(self.x).encode() - binary_key = PKCS8.wrap( - private_key, oid, passphrase, - protection, key_params=params, - randfunc=randfunc - ) - if passphrase: - key_type = 'ENCRYPTED PRIVATE' - else: - key_type = 'PRIVATE' - passphrase = None - else: - if format != 'PEM' and passphrase: - raise ValueError("DSA private key cannot be encrypted") - ints = [0, self.p, self.q, self.g, self.y, self.x] - binary_key = DerSequence(ints).encode() - key_type = "DSA PRIVATE" - else: - if pkcs8: - raise ValueError("PKCS#8 is only meaningful for private keys") - - binary_key = _create_subject_public_key_info(oid, - DerInteger(self.y), params) - key_type = "PUBLIC" - - if format == 'DER': - return binary_key - if format == 'PEM': - pem_str = PEM.encode( - binary_key, key_type + " KEY", - passphrase, randfunc - ) - return tobytes(pem_str) - raise ValueError("Unknown key format '%s'. Cannot export the DSA key." % format) - - # Backward-compatibility - exportKey = export_key - publickey = public_key - - # Methods defined in PyCrypto that we don't support anymore - - def sign(self, M, K): - raise NotImplementedError("Use module Crypto.Signature.DSS instead") - - def verify(self, M, signature): - raise NotImplementedError("Use module Crypto.Signature.DSS instead") - - def encrypt(self, plaintext, K): - raise NotImplementedError - - def decrypt(self, ciphertext): - raise NotImplementedError - - def blind(self, M, B): - raise NotImplementedError - - def unblind(self, M, B): - raise NotImplementedError - - def size(self): - raise NotImplementedError - - -def _generate_domain(L, randfunc): - """Generate a new set of DSA domain parameters""" - - N = { 1024:160, 2048:224, 3072:256 }.get(L) - if N is None: - raise ValueError("Invalid modulus length (%d)" % L) - - outlen = SHA256.digest_size * 8 - n = (L + outlen - 1) // outlen - 1 # ceil(L/outlen) -1 - b_ = L - 1 - (n * outlen) - - # Generate q (A.1.1.2) - q = Integer(4) - upper_bit = 1 << (N - 1) - while test_probable_prime(q, randfunc) != PROBABLY_PRIME: - seed = randfunc(64) - U = Integer.from_bytes(SHA256.new(seed).digest()) & (upper_bit - 1) - q = U | upper_bit | 1 - - assert(q.size_in_bits() == N) - - # Generate p (A.1.1.2) - offset = 1 - upper_bit = 1 << (L - 1) - while True: - V = [ SHA256.new(seed + Integer(offset + j).to_bytes()).digest() - for j in iter_range(n + 1) ] - V = [ Integer.from_bytes(v) for v in V ] - W = sum([V[i] * (1 << (i * outlen)) for i in iter_range(n)], - (V[n] & ((1 << b_) - 1)) * (1 << (n * outlen))) - - X = Integer(W + upper_bit) # 2^{L-1} < X < 2^{L} - assert(X.size_in_bits() == L) - - c = X % (q * 2) - p = X - (c - 1) # 2q divides (p-1) - if p.size_in_bits() == L and \ - test_probable_prime(p, randfunc) == PROBABLY_PRIME: - break - offset += n + 1 - - # Generate g (A.2.3, index=1) - e = (p - 1) // q - for count in itertools.count(1): - U = seed + b"ggen" + bchr(1) + Integer(count).to_bytes() - W = Integer.from_bytes(SHA256.new(U).digest()) - g = pow(W, e, p) - if g != 1: - break - - return (p, q, g, seed) - - -def generate(bits, randfunc=None, domain=None): - """Generate a new DSA key pair. - - The algorithm follows Appendix A.1/A.2 and B.1 of `FIPS 186-4`_, - respectively for domain generation and key pair generation. - - Args: - bits (integer): - Key length, or size (in bits) of the DSA modulus *p*. - It must be 1024, 2048 or 3072. - - randfunc (callable): - Random number generation function; it accepts a single integer N - and return a string of random data N bytes long. - If not specified, :func:`Crypto.Random.get_random_bytes` is used. - - domain (tuple): - The DSA domain parameters *p*, *q* and *g* as a list of 3 - integers. Size of *p* and *q* must comply to `FIPS 186-4`_. - If not specified, the parameters are created anew. - - Returns: - :class:`DsaKey` : a new DSA key object - - Raises: - ValueError : when **bits** is too little, too big, or not a multiple of 64. - - .. _FIPS 186-4: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - """ - - if randfunc is None: - randfunc = Random.get_random_bytes - - if domain: - p, q, g = map(Integer, domain) - - ## Perform consistency check on domain parameters - # P and Q must be prime - fmt_error = test_probable_prime(p) == COMPOSITE - fmt_error = test_probable_prime(q) == COMPOSITE - # Verify Lagrange's theorem for sub-group - fmt_error |= ((p - 1) % q) != 0 - fmt_error |= g <= 1 or g >= p - fmt_error |= pow(g, q, p) != 1 - if fmt_error: - raise ValueError("Invalid DSA domain parameters") - else: - p, q, g, _ = _generate_domain(bits, randfunc) - - L = p.size_in_bits() - N = q.size_in_bits() - - if L != bits: - raise ValueError("Mismatch between size of modulus (%d)" - " and 'bits' parameter (%d)" % (L, bits)) - - if (L, N) not in [(1024, 160), (2048, 224), - (2048, 256), (3072, 256)]: - raise ValueError("Lengths of p and q (%d, %d) are not compatible" - "to FIPS 186-3" % (L, N)) - - if not 1 < g < p: - raise ValueError("Incorrent DSA generator") - - # B.1.1 - c = Integer.random(exact_bits=N + 64, randfunc=randfunc) - x = c % (q - 1) + 1 # 1 <= x <= q-1 - y = pow(g, x, p) - - key_dict = { 'y':y, 'g':g, 'p':p, 'q':q, 'x':x } - return DsaKey(key_dict) - - -def construct(tup, consistency_check=True): - """Construct a DSA key from a tuple of valid DSA components. - - Args: - tup (tuple): - A tuple of long integers, with 4 or 5 items - in the following order: - - 1. Public key (*y*). - 2. Sub-group generator (*g*). - 3. Modulus, finite field order (*p*). - 4. Sub-group order (*q*). - 5. Private key (*x*). Optional. - - consistency_check (boolean): - If ``True``, the library will verify that the provided components - fulfil the main DSA properties. - - Raises: - ValueError: when the key being imported fails the most basic DSA validity checks. - - Returns: - :class:`DsaKey` : a DSA key object - """ - - key_dict = dict(zip(('y', 'g', 'p', 'q', 'x'), map(Integer, tup))) - key = DsaKey(key_dict) - - fmt_error = False - if consistency_check: - # P and Q must be prime - fmt_error = test_probable_prime(key.p) == COMPOSITE - fmt_error = test_probable_prime(key.q) == COMPOSITE - # Verify Lagrange's theorem for sub-group - fmt_error |= ((key.p - 1) % key.q) != 0 - fmt_error |= key.g <= 1 or key.g >= key.p - fmt_error |= pow(key.g, key.q, key.p) != 1 - # Public key - fmt_error |= key.y <= 0 or key.y >= key.p - if hasattr(key, 'x'): - fmt_error |= key.x <= 0 or key.x >= key.q - fmt_error |= pow(key.g, key.x, key.p) != key.y - - if fmt_error: - raise ValueError("Invalid DSA key components") - - return key - - -# Dss-Parms ::= SEQUENCE { -# p OCTET STRING, -# q OCTET STRING, -# g OCTET STRING -# } -# DSAPublicKey ::= INTEGER -- public key, y - -def _import_openssl_private(encoded, passphrase, params): - if params: - raise ValueError("DSA private key already comes with parameters") - der = DerSequence().decode(encoded, nr_elements=6, only_ints_expected=True) - if der[0] != 0: - raise ValueError("No version found") - tup = [der[comp] for comp in (4, 3, 1, 2, 5)] - return construct(tup) - - -def _import_subjectPublicKeyInfo(encoded, passphrase, params): - - algoid, encoded_key, emb_params = _expand_subject_public_key_info(encoded) - if algoid != oid: - raise ValueError("No DSA subjectPublicKeyInfo") - if params and emb_params: - raise ValueError("Too many DSA parameters") - - y = DerInteger().decode(encoded_key).value - p, q, g = list(DerSequence().decode(params or emb_params)) - tup = (y, g, p, q) - return construct(tup) - - -def _import_x509_cert(encoded, passphrase, params): - - sp_info = _extract_subject_public_key_info(encoded) - return _import_subjectPublicKeyInfo(sp_info, None, params) - - -def _import_pkcs8(encoded, passphrase, params): - if params: - raise ValueError("PKCS#8 already includes parameters") - k = PKCS8.unwrap(encoded, passphrase) - if k[0] != oid: - raise ValueError("No PKCS#8 encoded DSA key") - x = DerInteger().decode(k[1]).value - p, q, g = list(DerSequence().decode(k[2])) - tup = (pow(g, x, p), g, p, q, x) - return construct(tup) - - -def _import_key_der(key_data, passphrase, params): - """Import a DSA key (public or private half), encoded in DER form.""" - - decodings = (_import_openssl_private, - _import_subjectPublicKeyInfo, - _import_x509_cert, - _import_pkcs8) - - for decoding in decodings: - try: - return decoding(key_data, passphrase, params) - except ValueError: - pass - - raise ValueError("DSA key format is not supported") - - -def import_key(extern_key, passphrase=None): - """Import a DSA key. - - Args: - extern_key (string or byte string): - The DSA key to import. - - The following formats are supported for a DSA **public** key: - - - X.509 certificate (binary DER or PEM) - - X.509 ``subjectPublicKeyInfo`` (binary DER or PEM) - - OpenSSH (ASCII one-liner, see `RFC4253`_) - - The following formats are supported for a DSA **private** key: - - - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo`` - DER SEQUENCE (binary or PEM) - - OpenSSL/OpenSSH custom format (binary or PEM) - - For details about the PEM encoding, see `RFC1421`_/`RFC1423`_. - - passphrase (string): - In case of an encrypted private key, this is the pass phrase - from which the decryption key is derived. - - Encryption may be applied either at the `PKCS#8`_ or at the PEM level. - - Returns: - :class:`DsaKey` : a DSA key object - - Raises: - ValueError : when the given key cannot be parsed (possibly because - the pass phrase is wrong). - - .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt - .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt - .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt - .. _PKCS#8: http://www.ietf.org/rfc/rfc5208.txt - """ - - extern_key = tobytes(extern_key) - if passphrase is not None: - passphrase = tobytes(passphrase) - - if extern_key.startswith(b'-----'): - # This is probably a PEM encoded key - (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase) - if enc_flag: - passphrase = None - return _import_key_der(der, passphrase, None) - - if extern_key.startswith(b'ssh-dss '): - # This is probably a public OpenSSH key - keystring = binascii.a2b_base64(extern_key.split(b' ')[1]) - keyparts = [] - while len(keystring) > 4: - length = struct.unpack(">I", keystring[:4])[0] - keyparts.append(keystring[4:4 + length]) - keystring = keystring[4 + length:] - if keyparts[0] == b"ssh-dss": - tup = [Integer.from_bytes(keyparts[x]) for x in (4, 3, 1, 2)] - return construct(tup) - - if len(extern_key) > 0 and bord(extern_key[0]) == 0x30: - # This is probably a DER encoded key - return _import_key_der(extern_key, passphrase, None) - - raise ValueError("DSA key format is not supported") - - -# Backward compatibility -importKey = import_key - -#: `Object ID`_ for a DSA key. -#: -#: id-dsa ID ::= { iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 1 } -#: -#: .. _`Object ID`: http://www.alvestrand.no/objectid/1.2.840.10040.4.1.html -oid = "1.2.840.10040.4.1" diff --git a/Crypto/PublicKey/DSA.pyi b/Crypto/PublicKey/DSA.pyi deleted file mode 100644 index 354ac1f..0000000 --- a/Crypto/PublicKey/DSA.pyi +++ /dev/null @@ -1,31 +0,0 @@ -from typing import Dict, Tuple, Callable, Union, Optional - -__all__ = ['generate', 'construct', 'DsaKey', 'import_key' ] - -RNG = Callable[[int], bytes] - -class DsaKey(object): - def __init__(self, key_dict: Dict[str, int]) -> None: ... - def has_private(self) -> bool: ... - def can_encrypt(self) -> bool: ... # legacy - def can_sign(self) -> bool: ... # legacy - def public_key(self) -> DsaKey: ... - def __eq__(self, other: object) -> bool: ... - def __ne__(self, other: object) -> bool: ... - def __getstate__(self) -> None: ... - def domain(self) -> Tuple[int, int, int]: ... - def __repr__(self) -> str: ... - def __getattr__(self, item: str) -> int: ... - def export_key(self, format: Optional[str]="PEM", pkcs8: Optional[bool]=None, passphrase: Optional[str]=None, - protection: Optional[str]=None, randfunc: Optional[RNG]=None) -> bytes: ... - # Backward-compatibility - exportKey = export_key - publickey = public_key - -def generate(bits: int, randfunc: Optional[RNG]=None, domain: Optional[Tuple[int, int, int]]=None) -> DsaKey: ... -def construct(tup: Union[Tuple[int, int, int, int], Tuple[int, int, int, int, int]], consistency_check: Optional[bool]=True) -> DsaKey: ... -def import_key(extern_key: Union[str, bytes], passphrase: Optional[str]=None) -> DsaKey: ... -# Backward compatibility -importKey = import_key - -oid: str diff --git a/Crypto/PublicKey/ECC.py b/Crypto/PublicKey/ECC.py deleted file mode 100644 index 415eced..0000000 --- a/Crypto/PublicKey/ECC.py +++ /dev/null @@ -1,1182 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2015, Legrandin -# 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 re -import struct -import binascii -from collections import namedtuple - -from Crypto.Util.py3compat import bord, tobytes, tostr, bchr, is_string -from Crypto.Util.number import bytes_to_long, long_to_bytes - -from Crypto.Math.Numbers import Integer -from Crypto.Util.asn1 import (DerObjectId, DerOctetString, DerSequence, - DerBitString) - -from Crypto.PublicKey import (_expand_subject_public_key_info, - _create_subject_public_key_info, - _extract_subject_public_key_info) - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer, - SmartPointer, c_size_t, c_uint8_ptr, - c_ulonglong) - -from Crypto.Random import get_random_bytes -from Crypto.Random.random import getrandbits - - -_ec_lib = load_pycryptodome_raw_lib("Crypto.PublicKey._ec_ws", """ -typedef void EcContext; -typedef void EcPoint; -int ec_ws_new_context(EcContext **pec_ctx, - const uint8_t *modulus, - const uint8_t *b, - const uint8_t *order, - size_t len, - uint64_t seed); -void ec_free_context(EcContext *ec_ctx); -int ec_ws_new_point(EcPoint **pecp, - const uint8_t *x, - const uint8_t *y, - size_t len, - const EcContext *ec_ctx); -void ec_free_point(EcPoint *ecp); -int ec_ws_get_xy(uint8_t *x, - uint8_t *y, - size_t len, - const EcPoint *ecp); -int ec_ws_double(EcPoint *p); -int ec_ws_add(EcPoint *ecpa, EcPoint *ecpb); -int ec_ws_scalar(EcPoint *ecp, - const uint8_t *k, - size_t len, - uint64_t seed); -int ec_ws_clone(EcPoint **pecp2, const EcPoint *ecp); -int ec_ws_copy(EcPoint *ecp1, const EcPoint *ecp2); -int ec_ws_cmp(const EcPoint *ecp1, const EcPoint *ecp2); -int ec_ws_neg(EcPoint *p); -int ec_ws_normalize(EcPoint *ecp); -int ec_ws_is_pai(EcPoint *ecp); -""") - -_Curve = namedtuple("_Curve", "p b order Gx Gy G modulus_bits oid context desc openssh") -_curves = {} - - -p256_names = ["p256", "NIST P-256", "P-256", "prime256v1", "secp256r1", - "nistp256"] - - -def init_p256(): - p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff - b = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b - order = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 - Gx = 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296 - Gy = 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5 - - p256_modulus = long_to_bytes(p, 32) - p256_b = long_to_bytes(b, 32) - p256_order = long_to_bytes(order, 32) - - ec_p256_context = VoidPointer() - result = _ec_lib.ec_ws_new_context(ec_p256_context.address_of(), - c_uint8_ptr(p256_modulus), - c_uint8_ptr(p256_b), - c_uint8_ptr(p256_order), - c_size_t(len(p256_modulus)), - c_ulonglong(getrandbits(64)) - ) - if result: - raise ImportError("Error %d initializing P-256 context" % result) - - context = SmartPointer(ec_p256_context.get(), _ec_lib.ec_free_context) - p256 = _Curve(Integer(p), - Integer(b), - Integer(order), - Integer(Gx), - Integer(Gy), - None, - 256, - "1.2.840.10045.3.1.7", # ANSI X9.62 - context, - "NIST P-256", - "ecdsa-sha2-nistp256") - global p256_names - _curves.update(dict.fromkeys(p256_names, p256)) - - -init_p256() -del init_p256 - - -p384_names = ["p384", "NIST P-384", "P-384", "prime384v1", "secp384r1", - "nistp384"] - - -def init_p384(): - p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff - b = 0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef - order = 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973 - Gx = 0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760aB7 - Gy = 0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5F - - p384_modulus = long_to_bytes(p, 48) - p384_b = long_to_bytes(b, 48) - p384_order = long_to_bytes(order, 48) - - ec_p384_context = VoidPointer() - result = _ec_lib.ec_ws_new_context(ec_p384_context.address_of(), - c_uint8_ptr(p384_modulus), - c_uint8_ptr(p384_b), - c_uint8_ptr(p384_order), - c_size_t(len(p384_modulus)), - c_ulonglong(getrandbits(64)) - ) - if result: - raise ImportError("Error %d initializing P-384 context" % result) - - context = SmartPointer(ec_p384_context.get(), _ec_lib.ec_free_context) - p384 = _Curve(Integer(p), - Integer(b), - Integer(order), - Integer(Gx), - Integer(Gy), - None, - 384, - "1.3.132.0.34", # SEC 2 - context, - "NIST P-384", - "ecdsa-sha2-nistp384") - global p384_names - _curves.update(dict.fromkeys(p384_names, p384)) - - -init_p384() -del init_p384 - - -p521_names = ["p521", "NIST P-521", "P-521", "prime521v1", "secp521r1", - "nistp521"] - - -def init_p521(): - p = 0x000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - b = 0x00000051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00 - order = 0x000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409 - Gx = 0x000000c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66 - Gy = 0x0000011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650 - - p521_modulus = long_to_bytes(p, 66) - p521_b = long_to_bytes(b, 66) - p521_order = long_to_bytes(order, 66) - - ec_p521_context = VoidPointer() - result = _ec_lib.ec_ws_new_context(ec_p521_context.address_of(), - c_uint8_ptr(p521_modulus), - c_uint8_ptr(p521_b), - c_uint8_ptr(p521_order), - c_size_t(len(p521_modulus)), - c_ulonglong(getrandbits(64)) - ) - if result: - raise ImportError("Error %d initializing P-521 context" % result) - - context = SmartPointer(ec_p521_context.get(), _ec_lib.ec_free_context) - p521 = _Curve(Integer(p), - Integer(b), - Integer(order), - Integer(Gx), - Integer(Gy), - None, - 521, - "1.3.132.0.35", # SEC 2 - context, - "NIST P-521", - "ecdsa-sha2-nistp521") - global p521_names - _curves.update(dict.fromkeys(p521_names, p521)) - - -init_p521() -del init_p521 - - -class UnsupportedEccFeature(ValueError): - pass - - -class EccPoint(object): - """A class to abstract a point over an Elliptic Curve. - - The class support special methods for: - - * Adding two points: ``R = S + T`` - * In-place addition: ``S += T`` - * Negating a point: ``R = -T`` - * Comparing two points: ``if S == T: ...`` - * Multiplying a point by a scalar: ``R = S*k`` - * In-place multiplication by a scalar: ``T *= k`` - - :ivar x: The affine X-coordinate of the ECC point - :vartype x: integer - - :ivar y: The affine Y-coordinate of the ECC point - :vartype y: integer - - :ivar xy: The tuple with X- and Y- coordinates - """ - - def __init__(self, x, y, curve="p256"): - - try: - self._curve = _curves[curve] - except KeyError: - raise ValueError("Unknown curve name %s" % str(curve)) - self._curve_name = curve - - modulus_bytes = self.size_in_bytes() - context = self._curve.context - - xb = long_to_bytes(x, modulus_bytes) - yb = long_to_bytes(y, modulus_bytes) - if len(xb) != modulus_bytes or len(yb) != modulus_bytes: - raise ValueError("Incorrect coordinate length") - - self._point = VoidPointer() - result = _ec_lib.ec_ws_new_point(self._point.address_of(), - c_uint8_ptr(xb), - c_uint8_ptr(yb), - c_size_t(modulus_bytes), - context.get()) - if result: - if result == 15: - raise ValueError("The EC point does not belong to the curve") - raise ValueError("Error %d while instantiating an EC point" % result) - - # Ensure that object disposal of this Python object will (eventually) - # free the memory allocated by the raw library for the EC point - self._point = SmartPointer(self._point.get(), - _ec_lib.ec_free_point) - - def set(self, point): - self._point = VoidPointer() - result = _ec_lib.ec_ws_clone(self._point.address_of(), - point._point.get()) - if result: - raise ValueError("Error %d while cloning an EC point" % result) - - self._point = SmartPointer(self._point.get(), - _ec_lib.ec_free_point) - return self - - def __eq__(self, point): - return 0 == _ec_lib.ec_ws_cmp(self._point.get(), point._point.get()) - - def __neg__(self): - np = self.copy() - result = _ec_lib.ec_ws_neg(np._point.get()) - if result: - raise ValueError("Error %d while inverting an EC point" % result) - return np - - def copy(self): - """Return a copy of this point.""" - x, y = self.xy - np = EccPoint(x, y, self._curve_name) - return np - - def is_point_at_infinity(self): - """``True`` if this is the point-at-infinity.""" - return self.xy == (0, 0) - - def point_at_infinity(self): - """Return the point-at-infinity for the curve this point is on.""" - return EccPoint(0, 0, self._curve_name) - - @property - def x(self): - return self.xy[0] - - @property - def y(self): - return self.xy[1] - - @property - def xy(self): - modulus_bytes = self.size_in_bytes() - xb = bytearray(modulus_bytes) - yb = bytearray(modulus_bytes) - result = _ec_lib.ec_ws_get_xy(c_uint8_ptr(xb), - c_uint8_ptr(yb), - c_size_t(modulus_bytes), - self._point.get()) - if result: - raise ValueError("Error %d while encoding an EC point" % result) - - return (Integer(bytes_to_long(xb)), Integer(bytes_to_long(yb))) - - def size_in_bytes(self): - """Size of each coordinate, in bytes.""" - return (self.size_in_bits() + 7) // 8 - - def size_in_bits(self): - """Size of each coordinate, in bits.""" - return self._curve.modulus_bits - - def double(self): - """Double this point (in-place operation). - - :Return: - :class:`EccPoint` : this same object (to enable chaining) - """ - - result = _ec_lib.ec_ws_double(self._point.get()) - if result: - raise ValueError("Error %d while doubling an EC point" % result) - return self - - def __iadd__(self, point): - """Add a second point to this one""" - - result = _ec_lib.ec_ws_add(self._point.get(), point._point.get()) - if result: - if result == 16: - raise ValueError("EC points are not on the same curve") - raise ValueError("Error %d while adding two EC points" % result) - return self - - def __add__(self, point): - """Return a new point, the addition of this one and another""" - - np = self.copy() - np += point - return np - - def __imul__(self, scalar): - """Multiply this point by a scalar""" - - if scalar < 0: - raise ValueError("Scalar multiplication is only defined for non-negative integers") - sb = long_to_bytes(scalar) - result = _ec_lib.ec_ws_scalar(self._point.get(), - c_uint8_ptr(sb), - c_size_t(len(sb)), - c_ulonglong(getrandbits(64))) - if result: - raise ValueError("Error %d during scalar multiplication" % result) - return self - - def __mul__(self, scalar): - """Return a new point, the scalar product of this one""" - - np = self.copy() - np *= scalar - return np - - def __rmul__(self, left_hand): - return self.__mul__(left_hand) - - -# Last piece of initialization -p256_G = EccPoint(_curves['p256'].Gx, _curves['p256'].Gy, "p256") -p256 = _curves['p256']._replace(G=p256_G) -_curves.update(dict.fromkeys(p256_names, p256)) -del p256_G, p256, p256_names - -p384_G = EccPoint(_curves['p384'].Gx, _curves['p384'].Gy, "p384") -p384 = _curves['p384']._replace(G=p384_G) -_curves.update(dict.fromkeys(p384_names, p384)) -del p384_G, p384, p384_names - -p521_G = EccPoint(_curves['p521'].Gx, _curves['p521'].Gy, "p521") -p521 = _curves['p521']._replace(G=p521_G) -_curves.update(dict.fromkeys(p521_names, p521)) -del p521_G, p521, p521_names - - -class EccKey(object): - r"""Class defining an ECC key. - Do not instantiate directly. - Use :func:`generate`, :func:`construct` or :func:`import_key` instead. - - :ivar curve: The name of the ECC as defined in :numref:`curve_names`. - :vartype curve: string - - :ivar pointQ: an ECC point representating the public component - :vartype pointQ: :class:`EccPoint` - - :ivar d: A scalar representating the private component - :vartype d: integer - """ - - def __init__(self, **kwargs): - """Create a new ECC key - - Keywords: - curve : string - It must be *"p256"*, *"P-256"*, *"prime256v1"* or *"secp256r1"*. - d : integer - Only for a private key. It must be in the range ``[1..order-1]``. - point : EccPoint - Mandatory for a public key. If provided for a private key, - the implementation will NOT check whether it matches ``d``. - """ - - kwargs_ = dict(kwargs) - curve_name = kwargs_.pop("curve", None) - self._d = kwargs_.pop("d", None) - self._point = kwargs_.pop("point", None) - if kwargs_: - raise TypeError("Unknown parameters: " + str(kwargs_)) - - if curve_name not in _curves: - raise ValueError("Unsupported curve (%s)", curve_name) - self._curve = _curves[curve_name] - - if self._d is None: - if self._point is None: - raise ValueError("Either private or public ECC component must be specified, not both") - else: - self._d = Integer(self._d) - if not 1 <= self._d < self._curve.order: - raise ValueError("Invalid ECC private component") - - self.curve = self._curve.desc - - def __eq__(self, other): - if other.has_private() != self.has_private(): - return False - - return other.pointQ == self.pointQ - - def __repr__(self): - if self.has_private(): - extra = ", d=%d" % int(self._d) - else: - extra = "" - x, y = self.pointQ.xy - return "EccKey(curve='%s', point_x=%d, point_y=%d%s)" % (self._curve.desc, x, y, extra) - - def has_private(self): - """``True`` if this key can be used for making signatures or decrypting data.""" - - return self._d is not None - - def _sign(self, z, k): - assert 0 < k < self._curve.order - - order = self._curve.order - blind = Integer.random_range(min_inclusive=1, - max_exclusive=order) - - blind_d = self._d * blind - inv_blind_k = (blind * k).inverse(order) - - r = (self._curve.G * k).x % order - s = inv_blind_k * (blind * z + blind_d * r) % order - return (r, s) - - def _verify(self, z, rs): - order = self._curve.order - sinv = rs[1].inverse(order) - point1 = self._curve.G * ((sinv * z) % order) - point2 = self.pointQ * ((sinv * rs[0]) % order) - return (point1 + point2).x == rs[0] - - @property - def d(self): - if not self.has_private(): - raise ValueError("This is not a private ECC key") - return self._d - - @property - def pointQ(self): - if self._point is None: - self._point = self._curve.G * self._d - return self._point - - def public_key(self): - """A matching ECC public key. - - Returns: - a new :class:`EccKey` object - """ - - return EccKey(curve=self._curve.desc, point=self.pointQ) - - def _export_subjectPublicKeyInfo(self, compress): - - # See 2.2 in RFC5480 and 2.3.3 in SEC1 - # The first byte is: - # - 0x02: compressed, only X-coordinate, Y-coordinate is even - # - 0x03: compressed, only X-coordinate, Y-coordinate is odd - # - 0x04: uncompressed, X-coordinate is followed by Y-coordinate - # - # PAI is in theory encoded as 0x00. - - modulus_bytes = self.pointQ.size_in_bytes() - - if compress: - first_byte = 2 + self.pointQ.y.is_odd() - public_key = (bchr(first_byte) + - self.pointQ.x.to_bytes(modulus_bytes)) - else: - public_key = (b'\x04' + - self.pointQ.x.to_bytes(modulus_bytes) + - self.pointQ.y.to_bytes(modulus_bytes)) - - unrestricted_oid = "1.2.840.10045.2.1" - return _create_subject_public_key_info(unrestricted_oid, - public_key, - DerObjectId(self._curve.oid)) - - def _export_private_der(self, include_ec_params=True): - - assert self.has_private() - - # ECPrivateKey ::= SEQUENCE { - # version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), - # privateKey OCTET STRING, - # parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, - # publicKey [1] BIT STRING OPTIONAL - # } - - # Public key - uncompressed form - modulus_bytes = self.pointQ.size_in_bytes() - public_key = (b'\x04' + - self.pointQ.x.to_bytes(modulus_bytes) + - self.pointQ.y.to_bytes(modulus_bytes)) - - seq = [1, - DerOctetString(self.d.to_bytes(modulus_bytes)), - DerObjectId(self._curve.oid, explicit=0), - DerBitString(public_key, explicit=1)] - - if not include_ec_params: - del seq[2] - - return DerSequence(seq).encode() - - def _export_pkcs8(self, **kwargs): - from Crypto.IO import PKCS8 - - if kwargs.get('passphrase', None) is not None and 'protection' not in kwargs: - raise ValueError("At least the 'protection' parameter should be present") - - unrestricted_oid = "1.2.840.10045.2.1" - private_key = self._export_private_der(include_ec_params=False) - result = PKCS8.wrap(private_key, - unrestricted_oid, - key_params=DerObjectId(self._curve.oid), - **kwargs) - return result - - def _export_public_pem(self, compress): - from Crypto.IO import PEM - - encoded_der = self._export_subjectPublicKeyInfo(compress) - return PEM.encode(encoded_der, "PUBLIC KEY") - - def _export_private_pem(self, passphrase, **kwargs): - from Crypto.IO import PEM - - encoded_der = self._export_private_der() - return PEM.encode(encoded_der, "EC PRIVATE KEY", passphrase, **kwargs) - - def _export_private_clear_pkcs8_in_clear_pem(self): - from Crypto.IO import PEM - - encoded_der = self._export_pkcs8() - return PEM.encode(encoded_der, "PRIVATE KEY") - - def _export_private_encrypted_pkcs8_in_clear_pem(self, passphrase, **kwargs): - from Crypto.IO import PEM - - assert passphrase - if 'protection' not in kwargs: - raise ValueError("At least the 'protection' parameter should be present") - encoded_der = self._export_pkcs8(passphrase=passphrase, **kwargs) - return PEM.encode(encoded_der, "ENCRYPTED PRIVATE KEY") - - def _export_openssh(self, compress): - if self.has_private(): - raise ValueError("Cannot export OpenSSH private keys") - - desc = self._curve.openssh - modulus_bytes = self.pointQ.size_in_bytes() - - if compress: - first_byte = 2 + self.pointQ.y.is_odd() - public_key = (bchr(first_byte) + - self.pointQ.x.to_bytes(modulus_bytes)) - else: - public_key = (b'\x04' + - self.pointQ.x.to_bytes(modulus_bytes) + - self.pointQ.y.to_bytes(modulus_bytes)) - - middle = desc.split("-")[2] - comps = (tobytes(desc), tobytes(middle), public_key) - blob = b"".join([struct.pack(">I", len(x)) + x for x in comps]) - return desc + " " + tostr(binascii.b2a_base64(blob)) - - def export_key(self, **kwargs): - """Export this ECC key. - - Args: - format (string): - The format to use for encoding the key: - - - ``'DER'``. The key will be encoded in ASN.1 DER format (binary). - For a public key, the ASN.1 ``subjectPublicKeyInfo`` structure - defined in `RFC5480`_ will be used. - For a private key, the ASN.1 ``ECPrivateKey`` structure defined - in `RFC5915`_ is used instead (possibly within a PKCS#8 envelope, - see the ``use_pkcs8`` flag below). - - ``'PEM'``. The key will be encoded in a PEM_ envelope (ASCII). - - ``'OpenSSH'``. The key will be encoded in the OpenSSH_ format - (ASCII, public keys only). - - passphrase (byte string or string): - The passphrase to use for protecting the private key. - - use_pkcs8 (boolean): - Only relevant for private keys. - - If ``True`` (default and recommended), the `PKCS#8`_ representation - will be used. - - If ``False``, the much weaker `PEM encryption`_ mechanism will be used. - - protection (string): - When a private key is exported with password-protection - and PKCS#8 (both ``DER`` and ``PEM`` formats), this parameter MUST be - present and be a valid algorithm supported by :mod:`Crypto.IO.PKCS8`. - It is recommended to use ``PBKDF2WithHMAC-SHA1AndAES128-CBC``. - - compress (boolean): - If ``True``, a more compact representation of the public key - with the X-coordinate only is used. - - If ``False`` (default), the full public key will be exported. - - .. warning:: - If you don't provide a passphrase, the private key will be - exported in the clear! - - .. note:: - When exporting a private key with password-protection and `PKCS#8`_ - (both ``DER`` and ``PEM`` formats), any extra parameters - to ``export_key()`` will be passed to :mod:`Crypto.IO.PKCS8`. - - .. _PEM: http://www.ietf.org/rfc/rfc1421.txt - .. _`PEM encryption`: http://www.ietf.org/rfc/rfc1423.txt - .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt - .. _OpenSSH: http://www.openssh.com/txt/rfc5656.txt - .. _RFC5480: https://tools.ietf.org/html/rfc5480 - .. _RFC5915: http://www.ietf.org/rfc/rfc5915.txt - - Returns: - A multi-line string (for PEM and OpenSSH) or bytes (for DER) with the encoded key. - """ - - args = kwargs.copy() - ext_format = args.pop("format") - if ext_format not in ("PEM", "DER", "OpenSSH"): - raise ValueError("Unknown format '%s'" % ext_format) - - compress = args.pop("compress", False) - - if self.has_private(): - passphrase = args.pop("passphrase", None) - if is_string(passphrase): - passphrase = tobytes(passphrase) - if not passphrase: - raise ValueError("Empty passphrase") - use_pkcs8 = args.pop("use_pkcs8", True) - if ext_format == "PEM": - if use_pkcs8: - if passphrase: - return self._export_private_encrypted_pkcs8_in_clear_pem(passphrase, **args) - else: - return self._export_private_clear_pkcs8_in_clear_pem() - else: - return self._export_private_pem(passphrase, **args) - elif ext_format == "DER": - # DER - if passphrase and not use_pkcs8: - raise ValueError("Private keys can only be encrpyted with DER using PKCS#8") - if use_pkcs8: - return self._export_pkcs8(passphrase=passphrase, **args) - else: - return self._export_private_der() - else: - raise ValueError("Private keys cannot be exported in OpenSSH format") - else: # Public key - if args: - raise ValueError("Unexpected parameters: '%s'" % args) - if ext_format == "PEM": - return self._export_public_pem(compress) - elif ext_format == "DER": - return self._export_subjectPublicKeyInfo(compress) - else: - return self._export_openssh(compress) - - -def generate(**kwargs): - """Generate a new private key on the given curve. - - Args: - - curve (string): - Mandatory. It must be a curve name defined in :numref:`curve_names`. - - randfunc (callable): - Optional. The RNG to read randomness from. - If ``None``, :func:`Crypto.Random.get_random_bytes` is used. - """ - - curve_name = kwargs.pop("curve") - curve = _curves[curve_name] - randfunc = kwargs.pop("randfunc", get_random_bytes) - if kwargs: - raise TypeError("Unknown parameters: " + str(kwargs)) - - d = Integer.random_range(min_inclusive=1, - max_exclusive=curve.order, - randfunc=randfunc) - - return EccKey(curve=curve_name, d=d) - - -def construct(**kwargs): - """Build a new ECC key (private or public) starting - from some base components. - - Args: - - curve (string): - Mandatory. It must be a curve name defined in :numref:`curve_names`. - - d (integer): - Only for a private key. It must be in the range ``[1..order-1]``. - - point_x (integer): - Mandatory for a public key. X coordinate (affine) of the ECC point. - - point_y (integer): - Mandatory for a public key. Y coordinate (affine) of the ECC point. - - Returns: - :class:`EccKey` : a new ECC key object - """ - - curve_name = kwargs["curve"] - curve = _curves[curve_name] - point_x = kwargs.pop("point_x", None) - point_y = kwargs.pop("point_y", None) - - if "point" in kwargs: - raise TypeError("Unknown keyword: point") - - if None not in (point_x, point_y): - # ValueError is raised if the point is not on the curve - kwargs["point"] = EccPoint(point_x, point_y, curve_name) - - # Validate that the private key matches the public one - d = kwargs.get("d", None) - if d is not None and "point" in kwargs: - pub_key = curve.G * d - if pub_key.xy != (point_x, point_y): - raise ValueError("Private and public ECC keys do not match") - - return EccKey(**kwargs) - - -def _import_public_der(curve_oid, ec_point): - """Convert an encoded EC point into an EccKey object - - curve_name: string with the OID of the curve - ec_point: byte string with the EC point (not DER encoded) - - """ - - for curve_name, curve in _curves.items(): - if curve.oid == curve_oid: - break - else: - raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" % curve_oid) - - # See 2.2 in RFC5480 and 2.3.3 in SEC1 - # The first byte is: - # - 0x02: compressed, only X-coordinate, Y-coordinate is even - # - 0x03: compressed, only X-coordinate, Y-coordinate is odd - # - 0x04: uncompressed, X-coordinate is followed by Y-coordinate - # - # PAI is in theory encoded as 0x00. - - modulus_bytes = curve.p.size_in_bytes() - point_type = bord(ec_point[0]) - - # Uncompressed point - if point_type == 0x04: - if len(ec_point) != (1 + 2 * modulus_bytes): - raise ValueError("Incorrect EC point length") - x = Integer.from_bytes(ec_point[1:modulus_bytes+1]) - y = Integer.from_bytes(ec_point[modulus_bytes+1:]) - # Compressed point - elif point_type in (0x02, 0x3): - if len(ec_point) != (1 + modulus_bytes): - raise ValueError("Incorrect EC point length") - x = Integer.from_bytes(ec_point[1:]) - y = (x**3 - x*3 + curve.b).sqrt(curve.p) # Short Weierstrass - if point_type == 0x02 and y.is_odd(): - y = curve.p - y - if point_type == 0x03 and y.is_even(): - y = curve.p - y - else: - raise ValueError("Incorrect EC point encoding") - - return construct(curve=curve_name, point_x=x, point_y=y) - - -def _import_subjectPublicKeyInfo(encoded, *kwargs): - """Convert a subjectPublicKeyInfo into an EccKey object""" - - # See RFC5480 - - # Parse the generic subjectPublicKeyInfo structure - oid, ec_point, params = _expand_subject_public_key_info(encoded) - - # ec_point must be an encoded OCTET STRING - # params is encoded ECParameters - - # We accept id-ecPublicKey, id-ecDH, id-ecMQV without making any - # distiction for now. - - # Restrictions can be captured in the key usage certificate - # extension - unrestricted_oid = "1.2.840.10045.2.1" - ecdh_oid = "1.3.132.1.12" - ecmqv_oid = "1.3.132.1.13" - - if oid not in (unrestricted_oid, ecdh_oid, ecmqv_oid): - raise UnsupportedEccFeature("Unsupported ECC purpose (OID: %s)" % oid) - - # Parameters are mandatory for all three types - if not params: - raise ValueError("Missing ECC parameters") - - # ECParameters ::= CHOICE { - # namedCurve OBJECT IDENTIFIER - # -- implicitCurve NULL - # -- specifiedCurve SpecifiedECDomain - # } - # - # implicitCurve and specifiedCurve are not supported (as per RFC) - curve_oid = DerObjectId().decode(params).value - - return _import_public_der(curve_oid, ec_point) - - -def _import_private_der(encoded, passphrase, curve_oid=None): - - # See RFC5915 https://tools.ietf.org/html/rfc5915 - # - # ECPrivateKey ::= SEQUENCE { - # version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), - # privateKey OCTET STRING, - # parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, - # publicKey [1] BIT STRING OPTIONAL - # } - - private_key = DerSequence().decode(encoded, nr_elements=(3, 4)) - if private_key[0] != 1: - raise ValueError("Incorrect ECC private key version") - - try: - parameters = DerObjectId(explicit=0).decode(private_key[2]).value - if curve_oid is not None and parameters != curve_oid: - raise ValueError("Curve mismatch") - curve_oid = parameters - except ValueError: - pass - - if curve_oid is None: - raise ValueError("No curve found") - - for curve_name, curve in _curves.items(): - if curve.oid == curve_oid: - break - else: - raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" % curve_oid) - - scalar_bytes = DerOctetString().decode(private_key[1]).payload - modulus_bytes = curve.p.size_in_bytes() - if len(scalar_bytes) != modulus_bytes: - raise ValueError("Private key is too small") - d = Integer.from_bytes(scalar_bytes) - - # Decode public key (if any) - if len(private_key) == 4: - public_key_enc = DerBitString(explicit=1).decode(private_key[3]).value - public_key = _import_public_der(curve_oid, public_key_enc) - point_x = public_key.pointQ.x - point_y = public_key.pointQ.y - else: - point_x = point_y = None - - return construct(curve=curve_name, d=d, point_x=point_x, point_y=point_y) - - -def _import_pkcs8(encoded, passphrase): - from Crypto.IO import PKCS8 - - # From RFC5915, Section 1: - # - # Distributing an EC private key with PKCS#8 [RFC5208] involves including: - # a) id-ecPublicKey, id-ecDH, or id-ecMQV (from [RFC5480]) with the - # namedCurve as the parameters in the privateKeyAlgorithm field; and - # b) ECPrivateKey in the PrivateKey field, which is an OCTET STRING. - - algo_oid, private_key, params = PKCS8.unwrap(encoded, passphrase) - - # We accept id-ecPublicKey, id-ecDH, id-ecMQV without making any - # distiction for now. - unrestricted_oid = "1.2.840.10045.2.1" - ecdh_oid = "1.3.132.1.12" - ecmqv_oid = "1.3.132.1.13" - - if algo_oid not in (unrestricted_oid, ecdh_oid, ecmqv_oid): - raise UnsupportedEccFeature("Unsupported ECC purpose (OID: %s)" % algo_oid) - - curve_oid = DerObjectId().decode(params).value - - return _import_private_der(private_key, passphrase, curve_oid) - - -def _import_x509_cert(encoded, *kwargs): - - sp_info = _extract_subject_public_key_info(encoded) - return _import_subjectPublicKeyInfo(sp_info) - - -def _import_der(encoded, passphrase): - - try: - return _import_subjectPublicKeyInfo(encoded, passphrase) - except UnsupportedEccFeature as err: - raise err - except (ValueError, TypeError, IndexError): - pass - - try: - return _import_x509_cert(encoded, passphrase) - except UnsupportedEccFeature as err: - raise err - except (ValueError, TypeError, IndexError): - pass - - try: - return _import_private_der(encoded, passphrase) - except UnsupportedEccFeature as err: - raise err - except (ValueError, TypeError, IndexError): - pass - - try: - return _import_pkcs8(encoded, passphrase) - except UnsupportedEccFeature as err: - raise err - except (ValueError, TypeError, IndexError): - pass - - raise ValueError("Not an ECC DER key") - - -def _import_openssh_public(encoded): - keystring = binascii.a2b_base64(encoded.split(b' ')[1]) - - keyparts = [] - while len(keystring) > 4: - lk = struct.unpack(">I", keystring[:4])[0] - keyparts.append(keystring[4:4 + lk]) - keystring = keystring[4 + lk:] - - for curve_name, curve in _curves.items(): - middle = tobytes(curve.openssh.split("-")[2]) - if keyparts[1] == middle: - break - else: - raise ValueError("Unsupported ECC curve") - - return _import_public_der(curve.oid, keyparts[2]) - - -def _import_openssh_private_ecc(data, password): - - from ._openssh import (import_openssh_private_generic, - read_bytes, read_string, check_padding) - - ssh_name, decrypted = import_openssh_private_generic(data, password) - - name, decrypted = read_string(decrypted) - if name not in _curves: - raise UnsupportedEccFeature("Unsupported ECC curve %s" % name) - curve = _curves[name] - modulus_bytes = (curve.modulus_bits + 7) // 8 - - public_key, decrypted = read_bytes(decrypted) - - if bord(public_key[0]) != 4: - raise ValueError("Only uncompressed OpenSSH EC keys are supported") - if len(public_key) != 2 * modulus_bytes + 1: - raise ValueError("Incorrect public key length") - - point_x = Integer.from_bytes(public_key[1:1+modulus_bytes]) - point_y = Integer.from_bytes(public_key[1+modulus_bytes:]) - point = EccPoint(point_x, point_y, curve=name) - - private_key, decrypted = read_bytes(decrypted) - d = Integer.from_bytes(private_key) - - _, padded = read_string(decrypted) # Comment - check_padding(padded) - - return EccKey(curve=name, d=d, point=point) - - -def import_key(encoded, passphrase=None): - """Import an ECC key (public or private). - - Args: - encoded (bytes or multi-line string): - The ECC key to import. - - An ECC **public** key can be: - - - An X.509 certificate, binary (DER) or ASCII (PEM) - - An X.509 ``subjectPublicKeyInfo``, binary (DER) or ASCII (PEM) - - An OpenSSH line (e.g. the content of ``~/.ssh/id_ecdsa``, ASCII) - - An ECC **private** key can be: - - - In binary format (DER, see section 3 of `RFC5915`_ or `PKCS#8`_) - - In ASCII format (PEM or `OpenSSH 6.5+`_) - - Private keys can be in the clear or password-protected. - - For details about the PEM encoding, see `RFC1421`_/`RFC1423`_. - - passphrase (byte string): - The passphrase to use for decrypting a private key. - Encryption may be applied protected at the PEM level or at the PKCS#8 level. - This parameter is ignored if the key in input is not encrypted. - - Returns: - :class:`EccKey` : a new ECC key object - - Raises: - ValueError: when the given key cannot be parsed (possibly because - the pass phrase is wrong). - - .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt - .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt - .. _RFC5915: http://www.ietf.org/rfc/rfc5915.txt - .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt - .. _`OpenSSH 6.5+`: https://flak.tedunangst.com/post/new-openssh-key-format-and-bcrypt-pbkdf - """ - - from Crypto.IO import PEM - - encoded = tobytes(encoded) - if passphrase is not None: - passphrase = tobytes(passphrase) - - # PEM - if encoded.startswith(b'-----BEGIN OPENSSH PRIVATE KEY'): - text_encoded = tostr(encoded) - openssh_encoded, marker, enc_flag = PEM.decode(text_encoded, passphrase) - result = _import_openssh_private_ecc(openssh_encoded, passphrase) - return result - - elif encoded.startswith(b'-----'): - - text_encoded = tostr(encoded) - - # Remove any EC PARAMETERS section - # Ignore its content because the curve type must be already given in the key - ecparams_start = "-----BEGIN EC PARAMETERS-----" - ecparams_end = "-----END EC PARAMETERS-----" - text_encoded = re.sub(ecparams_start + ".*?" + ecparams_end, "", - text_encoded, - flags=re.DOTALL) - - der_encoded, marker, enc_flag = PEM.decode(text_encoded, passphrase) - if enc_flag: - passphrase = None - try: - result = _import_der(der_encoded, passphrase) - except UnsupportedEccFeature as uef: - raise uef - except ValueError: - raise ValueError("Invalid DER encoding inside the PEM file") - return result - - # OpenSSH - if encoded.startswith(b'ecdsa-sha2-'): - return _import_openssh_public(encoded) - - # DER - if len(encoded) > 0 and bord(encoded[0]) == 0x30: - return _import_der(encoded, passphrase) - - raise ValueError("ECC key format is not supported") - - -if __name__ == "__main__": - - import time - - d = 0xc51e4753afdec1e6b6c6a5b992f43f8dd0c7a8933072708b6522468b2ffb06fd - - point = _curves['p256'].G.copy() - count = 3000 - - start = time.time() - for x in range(count): - pointX = point * d - print("(P-256 G)", (time.time() - start) / count * 1000, "ms") - - start = time.time() - for x in range(count): - pointX = pointX * d - print("(P-256 arbitrary point)", (time.time() - start) / count * 1000, "ms") diff --git a/Crypto/PublicKey/ECC.pyi b/Crypto/PublicKey/ECC.pyi deleted file mode 100644 index acf3164..0000000 --- a/Crypto/PublicKey/ECC.pyi +++ /dev/null @@ -1,62 +0,0 @@ -from typing import Union, Callable, Optional, NamedTuple, List, Tuple, Dict, NamedTuple, Any - -from Crypto.Math.Numbers import Integer - -RNG = Callable[[int], bytes] - -class UnsupportedEccFeature(ValueError): ... -class EccPoint(object): - def __init__(self, x: Union[int, Integer], y: Union[int, Integer], curve: Optional[str] = ...) -> None: ... - def set(self, point: EccPoint) -> EccPoint: ... - def __eq__(self, point: object) -> bool: ... - def __neg__(self) -> EccPoint: ... - def copy(self) -> EccPoint: ... - def is_point_at_infinity(self) -> bool: ... - def point_at_infinity(self) -> EccPoint: ... - @property - def x(self) -> int: ... - @property - def y(self) -> int: ... - @property - def xy(self) -> Tuple[int, int]: ... - def size_in_bytes(self) -> int: ... - def size_in_bits(self) -> int: ... - def double(self) -> EccPoint: ... - def __iadd__(self, point: EccPoint) -> EccPoint: ... - def __add__(self, point: EccPoint) -> EccPoint: ... - def __imul__(self, scalar: int) -> EccPoint: ... - def __mul__(self, scalar: int) -> EccPoint: ... - -class EccKey(object): - curve: str - def __init__(self, *, curve: str = ..., d: int = ..., point: EccPoint = ...) -> None: ... - def __eq__(self, other: object) -> bool: ... - def __repr__(self) -> str: ... - def has_private(self) -> bool: ... - @property - def d(self) -> int: ... - @property - def pointQ(self) -> EccPoint: ... - def public_key(self) -> EccKey: ... - def export_key(self, **kwargs: Union[str, bytes, bool]) -> str: ... - - -_Curve = NamedTuple("_Curve", [('p', Integer), - ('order', Integer), - ('b', Integer), - ('Gx', Integer), - ('Gy', Integer), - ('G', EccPoint), - ('modulus_bits', int), - ('oid', str), - ('context', Any), - ('desc', str), - ('openssh', str), - ]) - -_curves : Dict[str, _Curve] - - -def generate(**kwargs: Union[str, RNG]) -> EccKey: ... -def construct(**kwargs: Union[str, int]) -> EccKey: ... -def import_key(encoded: Union[bytes, str], passphrase: Optional[str]=None) -> EccKey: ... diff --git a/Crypto/PublicKey/ElGamal.py b/Crypto/PublicKey/ElGamal.py deleted file mode 100644 index 3b10840..0000000 --- a/Crypto/PublicKey/ElGamal.py +++ /dev/null @@ -1,286 +0,0 @@ -# -# ElGamal.py : ElGamal encryption/decryption and signatures -# -# Part of the Python Cryptography Toolkit -# -# Originally written by: A.M. Kuchling -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -__all__ = ['generate', 'construct', 'ElGamalKey'] - -from Crypto import Random -from Crypto.Math.Primality import ( generate_probable_safe_prime, - test_probable_prime, COMPOSITE ) -from Crypto.Math.Numbers import Integer - -# Generate an ElGamal key with N bits -def generate(bits, randfunc): - """Randomly generate a fresh, new ElGamal key. - - The key will be safe for use for both encryption and signature - (although it should be used for **only one** purpose). - - Args: - bits (int): - Key length, or size (in bits) of the modulus *p*. - The recommended value is 2048. - randfunc (callable): - Random number generation function; it should accept - a single integer *N* and return a string of random - *N* random bytes. - - Return: - an :class:`ElGamalKey` object - """ - - obj=ElGamalKey() - - # Generate a safe prime p - # See Algorithm 4.86 in Handbook of Applied Cryptography - obj.p = generate_probable_safe_prime(exact_bits=bits, randfunc=randfunc) - q = (obj.p - 1) >> 1 - - # Generate generator g - while 1: - # Choose a square residue; it will generate a cyclic group of order q. - obj.g = pow(Integer.random_range(min_inclusive=2, - max_exclusive=obj.p, - randfunc=randfunc), 2, obj.p) - - # We must avoid g=2 because of Bleichenbacher's attack described - # in "Generating ElGamal signatures without knowning the secret key", - # 1996 - if obj.g in (1, 2): - continue - - # Discard g if it divides p-1 because of the attack described - # in Note 11.67 (iii) in HAC - if (obj.p - 1) % obj.g == 0: - continue - - # g^{-1} must not divide p-1 because of Khadir's attack - # described in "Conditions of the generator for forging ElGamal - # signature", 2011 - ginv = obj.g.inverse(obj.p) - if (obj.p - 1) % ginv == 0: - continue - - # Found - break - - # Generate private key x - obj.x = Integer.random_range(min_inclusive=2, - max_exclusive=obj.p-1, - randfunc=randfunc) - # Generate public key y - obj.y = pow(obj.g, obj.x, obj.p) - return obj - -def construct(tup): - r"""Construct an ElGamal key from a tuple of valid ElGamal components. - - The modulus *p* must be a prime. - The following conditions must apply: - - .. math:: - - \begin{align} - &1 < g < p-1 \\ - &g^{p-1} = 1 \text{ mod } 1 \\ - &1 < x < p-1 \\ - &g^x = y \text{ mod } p - \end{align} - - Args: - tup (tuple): - A tuple with either 3 or 4 integers, - in the following order: - - 1. Modulus (*p*). - 2. Generator (*g*). - 3. Public key (*y*). - 4. Private key (*x*). Optional. - - Raises: - ValueError: when the key being imported fails the most basic ElGamal validity checks. - - Returns: - an :class:`ElGamalKey` object - """ - - obj=ElGamalKey() - if len(tup) not in [3,4]: - raise ValueError('argument for construct() wrong length') - for i in range(len(tup)): - field = obj._keydata[i] - setattr(obj, field, Integer(tup[i])) - - fmt_error = test_probable_prime(obj.p) == COMPOSITE - fmt_error |= obj.g<=1 or obj.g>=obj.p - fmt_error |= pow(obj.g, obj.p-1, obj.p)!=1 - fmt_error |= obj.y<1 or obj.y>=obj.p - if len(tup)==4: - fmt_error |= obj.x<=1 or obj.x>=obj.p - fmt_error |= pow(obj.g, obj.x, obj.p)!=obj.y - - if fmt_error: - raise ValueError("Invalid ElGamal key components") - - return obj - -class ElGamalKey(object): - r"""Class defining an ElGamal key. - Do not instantiate directly. - Use :func:`generate` or :func:`construct` instead. - - :ivar p: Modulus - :vartype d: integer - - :ivar g: Generator - :vartype e: integer - - :ivar y: Public key component - :vartype y: integer - - :ivar x: Private key component - :vartype x: integer - """ - - #: Dictionary of ElGamal parameters. - #: - #: A public key will only have the following entries: - #: - #: - **y**, the public key. - #: - **g**, the generator. - #: - **p**, the modulus. - #: - #: A private key will also have: - #: - #: - **x**, the private key. - _keydata=['p', 'g', 'y', 'x'] - - def __init__(self, randfunc=None): - if randfunc is None: - randfunc = Random.new().read - self._randfunc = randfunc - - def _encrypt(self, M, K): - a=pow(self.g, K, self.p) - b=( pow(self.y, K, self.p)*M ) % self.p - return [int(a), int(b)] - - def _decrypt(self, M): - if (not hasattr(self, 'x')): - raise TypeError('Private key not available in this object') - r = Integer.random_range(min_inclusive=2, - max_exclusive=self.p-1, - randfunc=self._randfunc) - a_blind = (pow(self.g, r, self.p) * M[0]) % self.p - ax=pow(a_blind, self.x, self.p) - plaintext_blind = (ax.inverse(self.p) * M[1] ) % self.p - plaintext = (plaintext_blind * pow(self.y, r, self.p)) % self.p - return int(plaintext) - - def _sign(self, M, K): - if (not hasattr(self, 'x')): - raise TypeError('Private key not available in this object') - p1=self.p-1 - K = Integer(K) - if (K.gcd(p1)!=1): - raise ValueError('Bad K value: GCD(K,p-1)!=1') - a=pow(self.g, K, self.p) - t=(Integer(M)-self.x*a) % p1 - while t<0: t=t+p1 - b=(t*K.inverse(p1)) % p1 - return [int(a), int(b)] - - def _verify(self, M, sig): - sig = [Integer(x) for x in sig] - if sig[0]<1 or sig[0]>self.p-1: - return 0 - v1=pow(self.y, sig[0], self.p) - v1=(v1*pow(sig[0], sig[1], self.p)) % self.p - v2=pow(self.g, M, self.p) - if v1==v2: - return 1 - return 0 - - def has_private(self): - """Whether this is an ElGamal private key""" - - if hasattr(self, 'x'): - return 1 - else: - return 0 - - def can_encrypt(self): - return True - - def can_sign(self): - return True - - def publickey(self): - """A matching ElGamal public key. - - Returns: - a new :class:`ElGamalKey` object - """ - return construct((self.p, self.g, self.y)) - - def __eq__(self, other): - if bool(self.has_private()) != bool(other.has_private()): - return False - - result = True - for comp in self._keydata: - result = result and (getattr(self.key, comp, None) == - getattr(other.key, comp, None)) - return result - - def __ne__(self, other): - return not self.__eq__(other) - - def __getstate__(self): - # ElGamal key is not pickable - from pickle import PicklingError - raise PicklingError - - # Methods defined in PyCrypto that we don't support anymore - - def sign(self, M, K): - raise NotImplementedError - - def verify(self, M, signature): - raise NotImplementedError - - def encrypt(self, plaintext, K): - raise NotImplementedError - - def decrypt(self, ciphertext): - raise NotImplementedError - - def blind(self, M, B): - raise NotImplementedError - - def unblind(self, M, B): - raise NotImplementedError - - def size(self): - raise NotImplementedError diff --git a/Crypto/PublicKey/ElGamal.pyi b/Crypto/PublicKey/ElGamal.pyi deleted file mode 100644 index 9048531..0000000 --- a/Crypto/PublicKey/ElGamal.pyi +++ /dev/null @@ -1,18 +0,0 @@ -from typing import Callable, Union, Tuple, Optional - -__all__ = ['generate', 'construct', 'ElGamalKey'] - -RNG = Callable[[int], bytes] - -def generate(bits: int, randfunc: RNG) -> ElGamalKey: ... -def construct(tup: Union[Tuple[int, int, int], Tuple[int, int, int, int]]) -> ElGamalKey: ... - -class ElGamalKey(object): - def __init__(self, randfunc: Optional[RNG]=None) -> None: ... - def has_private(self) -> bool: ... - def can_encrypt(self) -> bool: ... - def can_sign(self) -> bool: ... - def publickey(self) -> ElGamalKey: ... - def __eq__(self, other: object) -> bool: ... - def __ne__(self, other: object) -> bool: ... - def __getstate__(self) -> None: ... diff --git a/Crypto/PublicKey/RSA.py b/Crypto/PublicKey/RSA.py deleted file mode 100644 index fda3b2a..0000000 --- a/Crypto/PublicKey/RSA.py +++ /dev/null @@ -1,799 +0,0 @@ -# -*- coding: utf-8 -*- -# =================================================================== -# -# Copyright (c) 2016, Legrandin -# 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. -# =================================================================== - -__all__ = ['generate', 'construct', 'import_key', - 'RsaKey', 'oid'] - -import binascii -import struct - -from Crypto import Random -from Crypto.Util.py3compat import tobytes, bord, tostr -from Crypto.Util.asn1 import DerSequence - -from Crypto.Math.Numbers import Integer -from Crypto.Math.Primality import (test_probable_prime, - generate_probable_prime, COMPOSITE) - -from Crypto.PublicKey import (_expand_subject_public_key_info, - _create_subject_public_key_info, - _extract_subject_public_key_info) - - -class RsaKey(object): - r"""Class defining an actual RSA key. - Do not instantiate directly. - Use :func:`generate`, :func:`construct` or :func:`import_key` instead. - - :ivar n: RSA modulus - :vartype n: integer - - :ivar e: RSA public exponent - :vartype e: integer - - :ivar d: RSA private exponent - :vartype d: integer - - :ivar p: First factor of the RSA modulus - :vartype p: integer - - :ivar q: Second factor of the RSA modulus - :vartype q: integer - - :ivar u: Chinese remainder component (:math:`p^{-1} \text{mod } q`) - :vartype q: integer - - :undocumented: exportKey, publickey - """ - - def __init__(self, **kwargs): - """Build an RSA key. - - :Keywords: - n : integer - The modulus. - e : integer - The public exponent. - d : integer - The private exponent. Only required for private keys. - p : integer - The first factor of the modulus. Only required for private keys. - q : integer - The second factor of the modulus. Only required for private keys. - u : integer - The CRT coefficient (inverse of p modulo q). Only required for - private keys. - """ - - input_set = set(kwargs.keys()) - public_set = set(('n', 'e')) - private_set = public_set | set(('p', 'q', 'd', 'u')) - if input_set not in (private_set, public_set): - raise ValueError("Some RSA components are missing") - for component, value in kwargs.items(): - setattr(self, "_" + component, value) - if input_set == private_set: - self._dp = self._d % (self._p - 1) # = (e⁻¹) mod (p-1) - self._dq = self._d % (self._q - 1) # = (e⁻¹) mod (q-1) - - @property - def n(self): - return int(self._n) - - @property - def e(self): - return int(self._e) - - @property - def d(self): - if not self.has_private(): - raise AttributeError("No private exponent available for public keys") - return int(self._d) - - @property - def p(self): - if not self.has_private(): - raise AttributeError("No CRT component 'p' available for public keys") - return int(self._p) - - @property - def q(self): - if not self.has_private(): - raise AttributeError("No CRT component 'q' available for public keys") - return int(self._q) - - @property - def u(self): - if not self.has_private(): - raise AttributeError("No CRT component 'u' available for public keys") - return int(self._u) - - def size_in_bits(self): - """Size of the RSA modulus in bits""" - return self._n.size_in_bits() - - def size_in_bytes(self): - """The minimal amount of bytes that can hold the RSA modulus""" - return (self._n.size_in_bits() - 1) // 8 + 1 - - def _encrypt(self, plaintext): - if not 0 <= plaintext < self._n: - raise ValueError("Plaintext too large") - return int(pow(Integer(plaintext), self._e, self._n)) - - def _decrypt(self, ciphertext): - if not 0 <= ciphertext < self._n: - raise ValueError("Ciphertext too large") - if not self.has_private(): - raise TypeError("This is not a private key") - - # Blinded RSA decryption (to prevent timing attacks): - # Step 1: Generate random secret blinding factor r, - # such that 0 < r < n-1 - r = Integer.random_range(min_inclusive=1, max_exclusive=self._n) - # Step 2: Compute c' = c * r**e mod n - cp = Integer(ciphertext) * pow(r, self._e, self._n) % self._n - # Step 3: Compute m' = c'**d mod n (normal RSA decryption) - m1 = pow(cp, self._dp, self._p) - m2 = pow(cp, self._dq, self._q) - h = ((m2 - m1) * self._u) % self._q - mp = h * self._p + m1 - # Step 4: Compute m = m**(r-1) mod n - result = (r.inverse(self._n) * mp) % self._n - # Verify no faults occurred - if ciphertext != pow(result, self._e, self._n): - raise ValueError("Fault detected in RSA decryption") - return result - - def has_private(self): - """Whether this is an RSA private key""" - - return hasattr(self, "_d") - - def can_encrypt(self): # legacy - return True - - def can_sign(self): # legacy - return True - - def public_key(self): - """A matching RSA public key. - - Returns: - a new :class:`RsaKey` object - """ - return RsaKey(n=self._n, e=self._e) - - def __eq__(self, other): - if self.has_private() != other.has_private(): - return False - if self.n != other.n or self.e != other.e: - return False - if not self.has_private(): - return True - return (self.d == other.d) - - def __ne__(self, other): - return not (self == other) - - def __getstate__(self): - # RSA key is not pickable - from pickle import PicklingError - raise PicklingError - - def __repr__(self): - if self.has_private(): - extra = ", d=%d, p=%d, q=%d, u=%d" % (int(self._d), int(self._p), - int(self._q), int(self._u)) - else: - extra = "" - return "RsaKey(n=%d, e=%d%s)" % (int(self._n), int(self._e), extra) - - def __str__(self): - if self.has_private(): - key_type = "Private" - else: - key_type = "Public" - return "%s RSA key at 0x%X" % (key_type, id(self)) - - def export_key(self, format='PEM', passphrase=None, pkcs=1, - protection=None, randfunc=None): - """Export this RSA key. - - Args: - format (string): - The format to use for wrapping the key: - - - *'PEM'*. (*Default*) Text encoding, done according to `RFC1421`_/`RFC1423`_. - - *'DER'*. Binary encoding. - - *'OpenSSH'*. Textual encoding, done according to OpenSSH specification. - Only suitable for public keys (not private keys). - - passphrase (string): - (*For private keys only*) The pass phrase used for protecting the output. - - pkcs (integer): - (*For private keys only*) The ASN.1 structure to use for - serializing the key. Note that even in case of PEM - encoding, there is an inner ASN.1 DER structure. - - With ``pkcs=1`` (*default*), the private key is encoded in a - simple `PKCS#1`_ structure (``RSAPrivateKey``). - - With ``pkcs=8``, the private key is encoded in a `PKCS#8`_ structure - (``PrivateKeyInfo``). - - .. note:: - This parameter is ignored for a public key. - For DER and PEM, an ASN.1 DER ``SubjectPublicKeyInfo`` - structure is always used. - - protection (string): - (*For private keys only*) - The encryption scheme to use for protecting the private key. - - If ``None`` (default), the behavior depends on :attr:`format`: - - - For *'DER'*, the *PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC* - scheme is used. The following operations are performed: - - 1. A 16 byte Triple DES key is derived from the passphrase - using :func:`Crypto.Protocol.KDF.PBKDF2` with 8 bytes salt, - and 1 000 iterations of :mod:`Crypto.Hash.HMAC`. - 2. The private key is encrypted using CBC. - 3. The encrypted key is encoded according to PKCS#8. - - - For *'PEM'*, the obsolete PEM encryption scheme is used. - It is based on MD5 for key derivation, and Triple DES for encryption. - - Specifying a value for :attr:`protection` is only meaningful for PKCS#8 - (that is, ``pkcs=8``) and only if a pass phrase is present too. - - The supported schemes for PKCS#8 are listed in the - :mod:`Crypto.IO.PKCS8` module (see :attr:`wrap_algo` parameter). - - randfunc (callable): - A function that provides random bytes. Only used for PEM encoding. - The default is :func:`Crypto.Random.get_random_bytes`. - - Returns: - byte string: the encoded key - - Raises: - ValueError:when the format is unknown or when you try to encrypt a private - key with *DER* format and PKCS#1. - - .. warning:: - If you don't provide a pass phrase, the private key will be - exported in the clear! - - .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt - .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt - .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt - .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt - """ - - if passphrase is not None: - passphrase = tobytes(passphrase) - - if randfunc is None: - randfunc = Random.get_random_bytes - - if format == 'OpenSSH': - e_bytes, n_bytes = [x.to_bytes() for x in (self._e, self._n)] - if bord(e_bytes[0]) & 0x80: - e_bytes = b'\x00' + e_bytes - if bord(n_bytes[0]) & 0x80: - n_bytes = b'\x00' + n_bytes - keyparts = [b'ssh-rsa', e_bytes, n_bytes] - keystring = b''.join([struct.pack(">I", len(kp)) + kp for kp in keyparts]) - return b'ssh-rsa ' + binascii.b2a_base64(keystring)[:-1] - - # DER format is always used, even in case of PEM, which simply - # encodes it into BASE64. - if self.has_private(): - binary_key = DerSequence([0, - self.n, - self.e, - self.d, - self.p, - self.q, - self.d % (self.p-1), - self.d % (self.q-1), - Integer(self.q).inverse(self.p) - ]).encode() - if pkcs == 1: - key_type = 'RSA PRIVATE KEY' - if format == 'DER' and passphrase: - raise ValueError("PKCS#1 private key cannot be encrypted") - else: # PKCS#8 - from Crypto.IO import PKCS8 - - if format == 'PEM' and protection is None: - key_type = 'PRIVATE KEY' - binary_key = PKCS8.wrap(binary_key, oid, None) - else: - key_type = 'ENCRYPTED PRIVATE KEY' - if not protection: - protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC' - binary_key = PKCS8.wrap(binary_key, oid, - passphrase, protection) - passphrase = None - else: - key_type = "PUBLIC KEY" - binary_key = _create_subject_public_key_info(oid, - DerSequence([self.n, - self.e]) - ) - - if format == 'DER': - return binary_key - if format == 'PEM': - from Crypto.IO import PEM - - pem_str = PEM.encode(binary_key, key_type, passphrase, randfunc) - return tobytes(pem_str) - - raise ValueError("Unknown key format '%s'. Cannot export the RSA key." % format) - - # Backward compatibility - exportKey = export_key - publickey = public_key - - # Methods defined in PyCrypto that we don't support anymore - def sign(self, M, K): - raise NotImplementedError("Use module Crypto.Signature.pkcs1_15 instead") - - def verify(self, M, signature): - raise NotImplementedError("Use module Crypto.Signature.pkcs1_15 instead") - - def encrypt(self, plaintext, K): - raise NotImplementedError("Use module Crypto.Cipher.PKCS1_OAEP instead") - - def decrypt(self, ciphertext): - raise NotImplementedError("Use module Crypto.Cipher.PKCS1_OAEP instead") - - def blind(self, M, B): - raise NotImplementedError - - def unblind(self, M, B): - raise NotImplementedError - - def size(self): - raise NotImplementedError - - -def generate(bits, randfunc=None, e=65537): - """Create a new RSA key pair. - - The algorithm closely follows NIST `FIPS 186-4`_ in its - sections B.3.1 and B.3.3. The modulus is the product of - two non-strong probable primes. - Each prime passes a suitable number of Miller-Rabin tests - with random bases and a single Lucas test. - - Args: - bits (integer): - Key length, or size (in bits) of the RSA modulus. - It must be at least 1024, but **2048 is recommended.** - The FIPS standard only defines 1024, 2048 and 3072. - randfunc (callable): - Function that returns random bytes. - The default is :func:`Crypto.Random.get_random_bytes`. - e (integer): - Public RSA exponent. It must be an odd positive integer. - It is typically a small number with very few ones in its - binary representation. - The FIPS standard requires the public exponent to be - at least 65537 (the default). - - Returns: an RSA key object (:class:`RsaKey`, with private key). - - .. _FIPS 186-4: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - """ - - if bits < 1024: - raise ValueError("RSA modulus length must be >= 1024") - if e % 2 == 0 or e < 3: - raise ValueError("RSA public exponent must be a positive, odd integer larger than 2.") - - if randfunc is None: - randfunc = Random.get_random_bytes - - d = n = Integer(1) - e = Integer(e) - - while n.size_in_bits() != bits and d < (1 << (bits // 2)): - # Generate the prime factors of n: p and q. - # By construciton, their product is always - # 2^{bits-1} < p*q < 2^bits. - size_q = bits // 2 - size_p = bits - size_q - - min_p = min_q = (Integer(1) << (2 * size_q - 1)).sqrt() - if size_q != size_p: - min_p = (Integer(1) << (2 * size_p - 1)).sqrt() - - def filter_p(candidate): - return candidate > min_p and (candidate - 1).gcd(e) == 1 - - p = generate_probable_prime(exact_bits=size_p, - randfunc=randfunc, - prime_filter=filter_p) - - min_distance = Integer(1) << (bits // 2 - 100) - - def filter_q(candidate): - return (candidate > min_q and - (candidate - 1).gcd(e) == 1 and - abs(candidate - p) > min_distance) - - q = generate_probable_prime(exact_bits=size_q, - randfunc=randfunc, - prime_filter=filter_q) - - n = p * q - lcm = (p - 1).lcm(q - 1) - d = e.inverse(lcm) - - if p > q: - p, q = q, p - - u = p.inverse(q) - - return RsaKey(n=n, e=e, d=d, p=p, q=q, u=u) - - -def construct(rsa_components, consistency_check=True): - r"""Construct an RSA key from a tuple of valid RSA components. - - The modulus **n** must be the product of two primes. - The public exponent **e** must be odd and larger than 1. - - In case of a private key, the following equations must apply: - - .. math:: - - \begin{align} - p*q &= n \\ - e*d &\equiv 1 ( \text{mod lcm} [(p-1)(q-1)]) \\ - p*u &\equiv 1 ( \text{mod } q) - \end{align} - - Args: - rsa_components (tuple): - A tuple of integers, with at least 2 and no - more than 6 items. The items come in the following order: - - 1. RSA modulus *n*. - 2. Public exponent *e*. - 3. Private exponent *d*. - Only required if the key is private. - 4. First factor of *n* (*p*). - Optional, but the other factor *q* must also be present. - 5. Second factor of *n* (*q*). Optional. - 6. CRT coefficient *q*, that is :math:`p^{-1} \text{mod }q`. Optional. - - consistency_check (boolean): - If ``True``, the library will verify that the provided components - fulfil the main RSA properties. - - Raises: - ValueError: when the key being imported fails the most basic RSA validity checks. - - Returns: An RSA key object (:class:`RsaKey`). - """ - - class InputComps(object): - pass - - input_comps = InputComps() - for (comp, value) in zip(('n', 'e', 'd', 'p', 'q', 'u'), rsa_components): - setattr(input_comps, comp, Integer(value)) - - n = input_comps.n - e = input_comps.e - if not hasattr(input_comps, 'd'): - key = RsaKey(n=n, e=e) - else: - d = input_comps.d - if hasattr(input_comps, 'q'): - p = input_comps.p - q = input_comps.q - else: - # Compute factors p and q from the private exponent d. - # We assume that n has no more than two factors. - # See 8.2.2(i) in Handbook of Applied Cryptography. - ktot = d * e - 1 - # The quantity d*e-1 is a multiple of phi(n), even, - # and can be represented as t*2^s. - t = ktot - while t % 2 == 0: - t //= 2 - # Cycle through all multiplicative inverses in Zn. - # The algorithm is non-deterministic, but there is a 50% chance - # any candidate a leads to successful factoring. - # See "Digitalized Signatures and Public Key Functions as Intractable - # as Factorization", M. Rabin, 1979 - spotted = False - a = Integer(2) - while not spotted and a < 100: - k = Integer(t) - # Cycle through all values a^{t*2^i}=a^k - while k < ktot: - cand = pow(a, k, n) - # Check if a^k is a non-trivial root of unity (mod n) - if cand != 1 and cand != (n - 1) and pow(cand, 2, n) == 1: - # We have found a number such that (cand-1)(cand+1)=0 (mod n). - # Either of the terms divides n. - p = Integer(n).gcd(cand + 1) - spotted = True - break - k *= 2 - # This value was not any good... let's try another! - a += 2 - if not spotted: - raise ValueError("Unable to compute factors p and q from exponent d.") - # Found ! - assert ((n % p) == 0) - q = n // p - - if hasattr(input_comps, 'u'): - u = input_comps.u - else: - u = p.inverse(q) - - # Build key object - key = RsaKey(n=n, e=e, d=d, p=p, q=q, u=u) - - # Verify consistency of the key - if consistency_check: - - # Modulus and public exponent must be coprime - if e <= 1 or e >= n: - raise ValueError("Invalid RSA public exponent") - if Integer(n).gcd(e) != 1: - raise ValueError("RSA public exponent is not coprime to modulus") - - # For RSA, modulus must be odd - if not n & 1: - raise ValueError("RSA modulus is not odd") - - if key.has_private(): - # Modulus and private exponent must be coprime - if d <= 1 or d >= n: - raise ValueError("Invalid RSA private exponent") - if Integer(n).gcd(d) != 1: - raise ValueError("RSA private exponent is not coprime to modulus") - # Modulus must be product of 2 primes - if p * q != n: - raise ValueError("RSA factors do not match modulus") - if test_probable_prime(p) == COMPOSITE: - raise ValueError("RSA factor p is composite") - if test_probable_prime(q) == COMPOSITE: - raise ValueError("RSA factor q is composite") - # See Carmichael theorem - phi = (p - 1) * (q - 1) - lcm = phi // (p - 1).gcd(q - 1) - if (e * d % int(lcm)) != 1: - raise ValueError("Invalid RSA condition") - if hasattr(key, 'u'): - # CRT coefficient - if u <= 1 or u >= q: - raise ValueError("Invalid RSA component u") - if (p * u % q) != 1: - raise ValueError("Invalid RSA component u with p") - - return key - - -def _import_pkcs1_private(encoded, *kwargs): - # RSAPrivateKey ::= SEQUENCE { - # version Version, - # modulus INTEGER, -- n - # publicExponent INTEGER, -- e - # privateExponent INTEGER, -- d - # prime1 INTEGER, -- p - # prime2 INTEGER, -- q - # exponent1 INTEGER, -- d mod (p-1) - # exponent2 INTEGER, -- d mod (q-1) - # coefficient INTEGER -- (inverse of q) mod p - # } - # - # Version ::= INTEGER - der = DerSequence().decode(encoded, nr_elements=9, only_ints_expected=True) - if der[0] != 0: - raise ValueError("No PKCS#1 encoding of an RSA private key") - return construct(der[1:6] + [Integer(der[4]).inverse(der[5])]) - - -def _import_pkcs1_public(encoded, *kwargs): - # RSAPublicKey ::= SEQUENCE { - # modulus INTEGER, -- n - # publicExponent INTEGER -- e - # } - der = DerSequence().decode(encoded, nr_elements=2, only_ints_expected=True) - return construct(der) - - -def _import_subjectPublicKeyInfo(encoded, *kwargs): - - algoid, encoded_key, params = _expand_subject_public_key_info(encoded) - if algoid != oid or params is not None: - raise ValueError("No RSA subjectPublicKeyInfo") - return _import_pkcs1_public(encoded_key) - - -def _import_x509_cert(encoded, *kwargs): - - sp_info = _extract_subject_public_key_info(encoded) - return _import_subjectPublicKeyInfo(sp_info) - - -def _import_pkcs8(encoded, passphrase): - from Crypto.IO import PKCS8 - - k = PKCS8.unwrap(encoded, passphrase) - if k[0] != oid: - raise ValueError("No PKCS#8 encoded RSA key") - return _import_keyDER(k[1], passphrase) - - -def _import_keyDER(extern_key, passphrase): - """Import an RSA key (public or private half), encoded in DER form.""" - - decodings = (_import_pkcs1_private, - _import_pkcs1_public, - _import_subjectPublicKeyInfo, - _import_x509_cert, - _import_pkcs8) - - for decoding in decodings: - try: - return decoding(extern_key, passphrase) - except ValueError: - pass - - raise ValueError("RSA key format is not supported") - - -def _import_openssh_private_rsa(data, password): - - from ._openssh import (import_openssh_private_generic, - read_bytes, read_string, check_padding) - - ssh_name, decrypted = import_openssh_private_generic(data, password) - - if ssh_name != "ssh-rsa": - raise ValueError("This SSH key is not RSA") - - n, decrypted = read_bytes(decrypted) - e, decrypted = read_bytes(decrypted) - d, decrypted = read_bytes(decrypted) - iqmp, decrypted = read_bytes(decrypted) - p, decrypted = read_bytes(decrypted) - q, decrypted = read_bytes(decrypted) - - _, padded = read_string(decrypted) # Comment - check_padding(padded) - - build = [Integer.from_bytes(x) for x in (n, e, d, q, p, iqmp)] - return construct(build) - - -def import_key(extern_key, passphrase=None): - """Import an RSA key (public or private). - - Args: - extern_key (string or byte string): - The RSA key to import. - - The following formats are supported for an RSA **public key**: - - - X.509 certificate (binary or PEM format) - - X.509 ``subjectPublicKeyInfo`` DER SEQUENCE (binary or PEM - encoding) - - `PKCS#1`_ ``RSAPublicKey`` DER SEQUENCE (binary or PEM encoding) - - An OpenSSH line (e.g. the content of ``~/.ssh/id_ecdsa``, ASCII) - - The following formats are supported for an RSA **private key**: - - - PKCS#1 ``RSAPrivateKey`` DER SEQUENCE (binary or PEM encoding) - - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo`` - DER SEQUENCE (binary or PEM encoding) - - OpenSSH (text format, introduced in `OpenSSH 6.5`_) - - For details about the PEM encoding, see `RFC1421`_/`RFC1423`_. - - passphrase (string or byte string): - For private keys only, the pass phrase that encrypts the key. - - Returns: An RSA key object (:class:`RsaKey`). - - Raises: - ValueError/IndexError/TypeError: - When the given key cannot be parsed (possibly because the pass - phrase is wrong). - - .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt - .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt - .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt - .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt - .. _`OpenSSH 6.5`: https://flak.tedunangst.com/post/new-openssh-key-format-and-bcrypt-pbkdf - """ - - from Crypto.IO import PEM - - extern_key = tobytes(extern_key) - if passphrase is not None: - passphrase = tobytes(passphrase) - - if extern_key.startswith(b'-----BEGIN OPENSSH PRIVATE KEY'): - text_encoded = tostr(extern_key) - openssh_encoded, marker, enc_flag = PEM.decode(text_encoded, passphrase) - result = _import_openssh_private_rsa(openssh_encoded, passphrase) - return result - - if extern_key.startswith(b'-----'): - # This is probably a PEM encoded key. - (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase) - if enc_flag: - passphrase = None - return _import_keyDER(der, passphrase) - - if extern_key.startswith(b'ssh-rsa '): - # This is probably an OpenSSH key - keystring = binascii.a2b_base64(extern_key.split(b' ')[1]) - keyparts = [] - while len(keystring) > 4: - length = struct.unpack(">I", keystring[:4])[0] - keyparts.append(keystring[4:4 + length]) - keystring = keystring[4 + length:] - e = Integer.from_bytes(keyparts[1]) - n = Integer.from_bytes(keyparts[2]) - return construct([n, e]) - - if len(extern_key) > 0 and bord(extern_key[0]) == 0x30: - # This is probably a DER encoded key - return _import_keyDER(extern_key, passphrase) - - raise ValueError("RSA key format is not supported") - - -# Backward compatibility -importKey = import_key - -#: `Object ID`_ for the RSA encryption algorithm. This OID often indicates -#: a generic RSA key, even when such key will be actually used for digital -#: signatures. -#: -#: .. _`Object ID`: http://www.alvestrand.no/objectid/1.2.840.113549.1.1.1.html -oid = "1.2.840.113549.1.1.1" diff --git a/Crypto/PublicKey/RSA.pyi b/Crypto/PublicKey/RSA.pyi deleted file mode 100644 index d436acf..0000000 --- a/Crypto/PublicKey/RSA.pyi +++ /dev/null @@ -1,51 +0,0 @@ -from typing import Callable, Union, Tuple, Optional - -__all__ = ['generate', 'construct', 'import_key', - 'RsaKey', 'oid'] - -RNG = Callable[[int], bytes] - -class RsaKey(object): - def __init__(self, **kwargs: int) -> None: ... - @property - def n(self) -> int: ... - @property - def e(self) -> int: ... - @property - def d(self) -> int: ... - @property - def p(self) -> int: ... - @property - def q(self) -> int: ... - @property - def u(self) -> int: ... - def size_in_bits(self) -> int: ... - def size_in_bytes(self) -> int: ... - def has_private(self) -> bool: ... - def can_encrypt(self) -> bool: ... # legacy - def can_sign(self) -> bool:... # legacy - def public_key(self) -> RsaKey: ... - def __eq__(self, other: object) -> bool: ... - def __ne__(self, other: object) -> bool: ... - def __getstate__(self) -> None: ... - def __repr__(self) -> str: ... - def __str__(self) -> str: ... - def export_key(self, format: Optional[str]="PEM", passphrase: Optional[str]=None, pkcs: Optional[int]=1, - protection: Optional[str]=None, randfunc: Optional[RNG]=None) -> bytes: ... - - # Backward compatibility - exportKey = export_key - publickey = public_key - -def generate(bits: int, randfunc: Optional[RNG]=None, e: Optional[int]=65537) -> RsaKey: ... -def construct(rsa_components: Union[Tuple[int, int], # n, e - Tuple[int, int, int], # n, e, d - Tuple[int, int, int, int, int], # n, e, d, p, q - Tuple[int, int, int, int, int, int]], # n, e, d, p, q, crt_q - consistency_check: Optional[bool]=True) -> RsaKey: ... -def import_key(extern_key: Union[str, bytes], passphrase: Optional[str]=None) -> RsaKey: ... - -# Backward compatibility -importKey = import_key - -oid: str diff --git a/Crypto/PublicKey/__init__.py b/Crypto/PublicKey/__init__.py deleted file mode 100644 index c9ff59b..0000000 --- a/Crypto/PublicKey/__init__.py +++ /dev/null @@ -1,95 +0,0 @@ -# -*- coding: utf-8 -*- -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -from Crypto.Util.asn1 import (DerSequence, DerInteger, DerBitString, - DerObjectId, DerNull) - - -def _expand_subject_public_key_info(encoded): - """Parse a SubjectPublicKeyInfo structure. - - It returns a triple with: - * OID (string) - * encoded public key (bytes) - * Algorithm parameters (bytes or None) - """ - - # - # SubjectPublicKeyInfo ::= SEQUENCE { - # algorithm AlgorithmIdentifier, - # subjectPublicKey BIT STRING - # } - # - # AlgorithmIdentifier ::= SEQUENCE { - # algorithm OBJECT IDENTIFIER, - # parameters ANY DEFINED BY algorithm OPTIONAL - # } - # - - spki = DerSequence().decode(encoded, nr_elements=2) - algo = DerSequence().decode(spki[0], nr_elements=(1,2)) - algo_oid = DerObjectId().decode(algo[0]) - spk = DerBitString().decode(spki[1]).value - - if len(algo) == 1: - algo_params = None - else: - try: - DerNull().decode(algo[1]) - algo_params = None - except: - algo_params = algo[1] - - return algo_oid.value, spk, algo_params - - -def _create_subject_public_key_info(algo_oid, secret_key, params=None): - - if params is None: - params = DerNull() - - spki = DerSequence([ - DerSequence([ - DerObjectId(algo_oid), - params]), - DerBitString(secret_key) - ]) - return spki.encode() - - -def _extract_subject_public_key_info(x509_certificate): - """Extract subjectPublicKeyInfo from a DER X.509 certificate.""" - - certificate = DerSequence().decode(x509_certificate, nr_elements=3) - tbs_certificate = DerSequence().decode(certificate[0], - nr_elements=range(6, 11)) - - index = 5 - try: - tbs_certificate[0] + 1 - # Version not present - version = 1 - except TypeError: - version = DerInteger(explicit=0).decode(tbs_certificate[0]).value - if version not in (2, 3): - raise ValueError("Incorrect X.509 certificate version") - index = 6 - - return tbs_certificate[index] diff --git a/Crypto/PublicKey/__init__.pyi b/Crypto/PublicKey/__init__.pyi deleted file mode 100644 index e69de29..0000000 diff --git a/Crypto/PublicKey/_ec_ws.abi3.so b/Crypto/PublicKey/_ec_ws.abi3.so deleted file mode 100644 index f7655f6..0000000 Binary files a/Crypto/PublicKey/_ec_ws.abi3.so and /dev/null differ diff --git a/Crypto/PublicKey/_openssh.py b/Crypto/PublicKey/_openssh.py deleted file mode 100644 index 88dacfc..0000000 --- a/Crypto/PublicKey/_openssh.py +++ /dev/null @@ -1,135 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2019, Helder Eijs -# 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 struct - -from Crypto.Cipher import AES -from Crypto.Hash import SHA512 -from Crypto.Protocol.KDF import _bcrypt_hash -from Crypto.Util.strxor import strxor -from Crypto.Util.py3compat import tostr, bchr, bord - - -def read_int4(data): - if len(data) < 4: - raise ValueError("Insufficient data") - value = struct.unpack(">I", data[:4])[0] - return value, data[4:] - - -def read_bytes(data): - size, data = read_int4(data) - if len(data) < size: - raise ValueError("Insufficient data (V)") - return data[:size], data[size:] - - -def read_string(data): - s, d = read_bytes(data) - return tostr(s), d - - -def check_padding(pad): - for v, x in enumerate(pad): - if bord(x) != ((v + 1) & 0xFF): - raise ValueError("Incorrect padding") - - -def import_openssh_private_generic(data, password): - # https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.key?annotate=HEAD - # https://github.com/openssh/openssh-portable/blob/master/sshkey.c - # https://coolaj86.com/articles/the-openssh-private-key-format/ - # https://coolaj86.com/articles/the-ssh-public-key-format/ - - if not data.startswith(b'openssh-key-v1\x00'): - raise ValueError("Incorrect magic value") - data = data[15:] - - ciphername, data = read_string(data) - kdfname, data = read_string(data) - kdfoptions, data = read_bytes(data) - number_of_keys, data = read_int4(data) - - if number_of_keys != 1: - raise ValueError("We only handle 1 key at a time") - - _, data = read_string(data) # Public key - encrypted, data = read_bytes(data) - if data: - raise ValueError("Too much data") - - if len(encrypted) % 8 != 0: - raise ValueError("Incorrect payload length") - - # Decrypt if necessary - if ciphername == 'none': - decrypted = encrypted - else: - if (ciphername, kdfname) != ('aes256-ctr', 'bcrypt'): - raise ValueError("Unsupported encryption scheme %s/%s" % (ciphername, kdfname)) - - salt, kdfoptions = read_bytes(kdfoptions) - iterations, kdfoptions = read_int4(kdfoptions) - - if len(salt) != 16: - raise ValueError("Incorrect salt length") - if kdfoptions: - raise ValueError("Too much data in kdfoptions") - - pwd_sha512 = SHA512.new(password).digest() - # We need 32+16 = 48 bytes, therefore 2 bcrypt outputs are sufficient - stripes = [] - constant = b"OxychromaticBlowfishSwatDynamite" - for count in range(1, 3): - salt_sha512 = SHA512.new(salt + struct.pack(">I", count)).digest() - out_le = _bcrypt_hash(pwd_sha512, 6, salt_sha512, constant, False) - out = struct.pack("IIIIIIII", out_le)) - acc = bytearray(out) - for _ in range(1, iterations): - out_le = _bcrypt_hash(pwd_sha512, 6, SHA512.new(out).digest(), constant, False) - out = struct.pack("IIIIIIII", out_le)) - strxor(acc, out, output=acc) - stripes.append(acc[:24]) - - result = b"".join([bchr(a)+bchr(b) for (a, b) in zip(*stripes)]) - - cipher = AES.new(result[:32], - AES.MODE_CTR, - nonce=b"", - initial_value=result[32:32+16]) - decrypted = cipher.decrypt(encrypted) - - checkint1, decrypted = read_int4(decrypted) - checkint2, decrypted = read_int4(decrypted) - if checkint1 != checkint2: - raise ValueError("Incorrect checksum") - ssh_name, decrypted = read_string(decrypted) - - return ssh_name, decrypted diff --git a/Crypto/PublicKey/_openssh.pyi b/Crypto/PublicKey/_openssh.pyi deleted file mode 100644 index 15f3677..0000000 --- a/Crypto/PublicKey/_openssh.pyi +++ /dev/null @@ -1,7 +0,0 @@ -from typing import Tuple - -def read_int4(data: bytes) -> Tuple[int, bytes]: ... -def read_bytes(data: bytes) -> Tuple[bytes, bytes]: ... -def read_string(data: bytes) -> Tuple[str, bytes]: ... -def check_padding(pad: bytes) -> None: ... -def import_openssh_private_generic(data: bytes, password: bytes) -> Tuple[str, bytes]: ... diff --git a/Crypto/Random/__init__.py b/Crypto/Random/__init__.py deleted file mode 100644 index 0f83a07..0000000 --- a/Crypto/Random/__init__.py +++ /dev/null @@ -1,57 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Random/__init__.py : PyCrypto random number generation -# -# =================================================================== -# 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. -# =================================================================== - -__all__ = ['new', 'get_random_bytes'] - -from os import urandom - -class _UrandomRNG(object): - - def read(self, n): - """Return a random byte string of the desired size.""" - return urandom(n) - - def flush(self): - """Method provided for backward compatibility only.""" - pass - - def reinit(self): - """Method provided for backward compatibility only.""" - pass - - def close(self): - """Method provided for backward compatibility only.""" - pass - - -def new(*args, **kwargs): - """Return a file-like object that outputs cryptographically random bytes.""" - return _UrandomRNG() - - -def atfork(): - pass - - -#: Function that returns a random byte string of the desired size. -get_random_bytes = urandom - diff --git a/Crypto/Random/__init__.pyi b/Crypto/Random/__init__.pyi deleted file mode 100644 index ddc5b9b..0000000 --- a/Crypto/Random/__init__.pyi +++ /dev/null @@ -1,19 +0,0 @@ -from typing import Any - -__all__ = ['new', 'get_random_bytes'] - -from os import urandom - -class _UrandomRNG(object): - - def read(self, n: int) -> bytes:... - def flush(self) -> None: ... - def reinit(self) -> None: ... - def close(self) -> None: ... - -def new(*args: Any, **kwargs: Any) -> _UrandomRNG: ... - -def atfork() -> None: ... - -get_random_bytes = urandom - diff --git a/Crypto/Random/__pycache__/__init__.cpython-36.pyc b/Crypto/Random/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index bf789ae..0000000 Binary files a/Crypto/Random/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Random/random.py b/Crypto/Random/random.py deleted file mode 100644 index 5389b3b..0000000 --- a/Crypto/Random/random.py +++ /dev/null @@ -1,138 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Random/random.py : Strong alternative for the standard 'random' module -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# 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. -# =================================================================== - -__all__ = ['StrongRandom', 'getrandbits', 'randrange', 'randint', 'choice', 'shuffle', 'sample'] - -from Crypto import Random - -from Crypto.Util.py3compat import is_native_int - -class StrongRandom(object): - def __init__(self, rng=None, randfunc=None): - if randfunc is None and rng is None: - self._randfunc = None - elif randfunc is not None and rng is None: - self._randfunc = randfunc - elif randfunc is None and rng is not None: - self._randfunc = rng.read - else: - raise ValueError("Cannot specify both 'rng' and 'randfunc'") - - def getrandbits(self, k): - """Return an integer with k random bits.""" - - if self._randfunc is None: - self._randfunc = Random.new().read - mask = (1 << k) - 1 - return mask & bytes_to_long(self._randfunc(ceil_div(k, 8))) - - def randrange(self, *args): - """randrange([start,] stop[, step]): - Return a randomly-selected element from range(start, stop, step).""" - if len(args) == 3: - (start, stop, step) = args - elif len(args) == 2: - (start, stop) = args - step = 1 - elif len(args) == 1: - (stop,) = args - start = 0 - step = 1 - else: - raise TypeError("randrange expected at most 3 arguments, got %d" % (len(args),)) - if (not is_native_int(start) or not is_native_int(stop) or not - is_native_int(step)): - raise TypeError("randrange requires integer arguments") - if step == 0: - raise ValueError("randrange step argument must not be zero") - - num_choices = ceil_div(stop - start, step) - if num_choices < 0: - num_choices = 0 - if num_choices < 1: - raise ValueError("empty range for randrange(%r, %r, %r)" % (start, stop, step)) - - # Pick a random number in the range of possible numbers - r = num_choices - while r >= num_choices: - r = self.getrandbits(size(num_choices)) - - return start + (step * r) - - def randint(self, a, b): - """Return a random integer N such that a <= N <= b.""" - if not is_native_int(a) or not is_native_int(b): - raise TypeError("randint requires integer arguments") - N = self.randrange(a, b+1) - assert a <= N <= b - return N - - def choice(self, seq): - """Return a random element from a (non-empty) sequence. - - If the seqence is empty, raises IndexError. - """ - if len(seq) == 0: - raise IndexError("empty sequence") - return seq[self.randrange(len(seq))] - - def shuffle(self, x): - """Shuffle the sequence in place.""" - # Fisher-Yates shuffle. O(n) - # See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle - # Working backwards from the end of the array, we choose a random item - # from the remaining items until all items have been chosen. - for i in range(len(x)-1, 0, -1): # iterate from len(x)-1 downto 1 - j = self.randrange(0, i+1) # choose random j such that 0 <= j <= i - x[i], x[j] = x[j], x[i] # exchange x[i] and x[j] - - def sample(self, population, k): - """Return a k-length list of unique elements chosen from the population sequence.""" - - num_choices = len(population) - if k > num_choices: - raise ValueError("sample larger than population") - - retval = [] - selected = {} # we emulate a set using a dict here - for i in range(k): - r = None - while r is None or r in selected: - r = self.randrange(num_choices) - retval.append(population[r]) - selected[r] = 1 - return retval - -_r = StrongRandom() -getrandbits = _r.getrandbits -randrange = _r.randrange -randint = _r.randint -choice = _r.choice -shuffle = _r.shuffle -sample = _r.sample - -# These are at the bottom to avoid problems with recursive imports -from Crypto.Util.number import ceil_div, bytes_to_long, long_to_bytes, size - -# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/Crypto/Random/random.pyi b/Crypto/Random/random.pyi deleted file mode 100644 index f873c4a..0000000 --- a/Crypto/Random/random.pyi +++ /dev/null @@ -1,20 +0,0 @@ -from typing import Callable, Tuple, Union, Sequence, Any, Optional - -__all__ = ['StrongRandom', 'getrandbits', 'randrange', 'randint', 'choice', 'shuffle', 'sample'] - -class StrongRandom(object): - def __init__(self, rng: Optional[Any]=None, randfunc: Optional[Callable]=None) -> None: ... # TODO What is rng? - def getrandbits(self, k: int) -> int: ... - def randrange(self, start: int, stop: int = ..., step: int = ...) -> int: ... - def randint(self, a: int, b: int) -> int: ... - def choice(self, seq: Sequence) -> object: ... - def shuffle(self, x: Sequence) -> None: ... - def sample(self, population: Sequence, k: int) -> list: ... - -_r = StrongRandom() -getrandbits = _r.getrandbits -randrange = _r.randrange -randint = _r.randint -choice = _r.choice -shuffle = _r.shuffle -sample = _r.sample diff --git a/Crypto/SelfTest/Cipher/__init__.py b/Crypto/SelfTest/Cipher/__init__.py deleted file mode 100644 index 05fc139..0000000 --- a/Crypto/SelfTest/Cipher/__init__.py +++ /dev/null @@ -1,60 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Cipher/__init__.py: Self-test for cipher modules -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# 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: diff --git a/Crypto/SelfTest/Cipher/__pycache__/__init__.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index 08e0399..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/__pycache__/common.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/common.cpython-36.pyc deleted file mode 100644 index 9d9ffca..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/common.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/__pycache__/test_AES.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/test_AES.cpython-36.pyc deleted file mode 100644 index 8867590..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/test_AES.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/__pycache__/test_ARC2.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/test_ARC2.cpython-36.pyc deleted file mode 100644 index 4d48ce4..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/test_ARC2.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/__pycache__/test_ARC4.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/test_ARC4.cpython-36.pyc deleted file mode 100644 index ecf9cae..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/test_ARC4.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/__pycache__/test_Blowfish.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/test_Blowfish.cpython-36.pyc deleted file mode 100644 index 89fbdbe..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/test_Blowfish.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/__pycache__/test_CAST.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/test_CAST.cpython-36.pyc deleted file mode 100644 index 812eea9..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/test_CAST.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/__pycache__/test_CBC.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/test_CBC.cpython-36.pyc deleted file mode 100644 index 397bfa6..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/test_CBC.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/__pycache__/test_CCM.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/test_CCM.cpython-36.pyc deleted file mode 100644 index 6960325..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/test_CCM.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/__pycache__/test_CFB.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/test_CFB.cpython-36.pyc deleted file mode 100644 index 9cd6f6d..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/test_CFB.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/__pycache__/test_CTR.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/test_CTR.cpython-36.pyc deleted file mode 100644 index fb7d7ed..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/test_CTR.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/__pycache__/test_ChaCha20.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/test_ChaCha20.cpython-36.pyc deleted file mode 100644 index 8e6e235..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/test_ChaCha20.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/__pycache__/test_ChaCha20_Poly1305.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/test_ChaCha20_Poly1305.cpython-36.pyc deleted file mode 100644 index c2b081f..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/test_ChaCha20_Poly1305.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/__pycache__/test_DES.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/test_DES.cpython-36.pyc deleted file mode 100644 index af93aa8..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/test_DES.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/__pycache__/test_DES3.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/test_DES3.cpython-36.pyc deleted file mode 100644 index 45e2167..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/test_DES3.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/__pycache__/test_EAX.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/test_EAX.cpython-36.pyc deleted file mode 100644 index 890669e..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/test_EAX.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/__pycache__/test_GCM.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/test_GCM.cpython-36.pyc deleted file mode 100644 index 92e3baf..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/test_GCM.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/__pycache__/test_OCB.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/test_OCB.cpython-36.pyc deleted file mode 100644 index 4c5cf01..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/test_OCB.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/__pycache__/test_OFB.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/test_OFB.cpython-36.pyc deleted file mode 100644 index 9eb57d3..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/test_OFB.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/__pycache__/test_OpenPGP.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/test_OpenPGP.cpython-36.pyc deleted file mode 100644 index 098bc40..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/test_OpenPGP.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/__pycache__/test_SIV.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/test_SIV.cpython-36.pyc deleted file mode 100644 index 0333a3f..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/test_SIV.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/__pycache__/test_Salsa20.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/test_Salsa20.cpython-36.pyc deleted file mode 100644 index bdab1fe..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/test_Salsa20.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/__pycache__/test_pkcs1_15.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/test_pkcs1_15.cpython-36.pyc deleted file mode 100644 index 8c8ac75..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/test_pkcs1_15.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/__pycache__/test_pkcs1_oaep.cpython-36.pyc b/Crypto/SelfTest/Cipher/__pycache__/test_pkcs1_oaep.cpython-36.pyc deleted file mode 100644 index b91abf3..0000000 Binary files a/Crypto/SelfTest/Cipher/__pycache__/test_pkcs1_oaep.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Cipher/common.py b/Crypto/SelfTest/Cipher/common.py deleted file mode 100644 index 4ba2c33..0000000 --- a/Crypto/SelfTest/Cipher/common.py +++ /dev/null @@ -1,512 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Hash/common.py: Common code for Crypto.SelfTest.Hash -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# 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), - ] - - import sys - if sys.version[:3] != '2.6': - 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: diff --git a/Crypto/SelfTest/Cipher/test_AES.py b/Crypto/SelfTest/Cipher/test_AES.py deleted file mode 100644 index 116deec..0000000 --- a/Crypto/SelfTest/Cipher/test_AES.py +++ /dev/null @@ -1,1351 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Cipher/AES.py: Self-test for the AES cipher -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# 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.AES""" - -from __future__ import print_function - -import unittest -from Crypto.Hash import SHA256 -from Crypto.Cipher import AES -from Crypto.Util.py3compat import * -from binascii import hexlify - -# This is a list of (plaintext, ciphertext, key[, description[, params]]) tuples. -test_data = [ - # FIPS PUB 197 test vectors - # http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf - - ('00112233445566778899aabbccddeeff', '69c4e0d86a7b0430d8cdb78070b4c55a', - '000102030405060708090a0b0c0d0e0f', 'FIPS 197 C.1 (AES-128)'), - - ('00112233445566778899aabbccddeeff', 'dda97ca4864cdfe06eaf70a0ec0d7191', - '000102030405060708090a0b0c0d0e0f1011121314151617', - 'FIPS 197 C.2 (AES-192)'), - - ('00112233445566778899aabbccddeeff', '8ea2b7ca516745bfeafc49904b496089', - '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', - 'FIPS 197 C.3 (AES-256)'), - - # Rijndael128 test vectors - # Downloaded 2008-09-13 from - # http://www.iaik.tugraz.at/Research/krypto/AES/old/~rijmen/rijndael/testvalues.tar.gz - - # ecb_tbl.txt, KEYSIZE=128 - ('506812a45f08c889b97f5980038b8359', 'd8f532538289ef7d06b506a4fd5be9c9', - '00010203050607080a0b0c0d0f101112', - 'ecb-tbl-128: I=1'), - ('5c6d71ca30de8b8b00549984d2ec7d4b', '59ab30f4d4ee6e4ff9907ef65b1fb68c', - '14151617191a1b1c1e1f202123242526', - 'ecb-tbl-128: I=2'), - ('53f3f4c64f8616e4e7c56199f48f21f6', 'bf1ed2fcb2af3fd41443b56d85025cb1', - '28292a2b2d2e2f30323334353738393a', - 'ecb-tbl-128: I=3'), - ('a1eb65a3487165fb0f1c27ff9959f703', '7316632d5c32233edcb0780560eae8b2', - '3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-128: I=4'), - ('3553ecf0b1739558b08e350a98a39bfa', '408c073e3e2538072b72625e68b8364b', - '50515253555657585a5b5c5d5f606162', - 'ecb-tbl-128: I=5'), - ('67429969490b9711ae2b01dc497afde8', 'e1f94dfa776597beaca262f2f6366fea', - '64656667696a6b6c6e6f707173747576', - 'ecb-tbl-128: I=6'), - ('93385c1f2aec8bed192f5a8e161dd508', 'f29e986c6a1c27d7b29ffd7ee92b75f1', - '78797a7b7d7e7f80828384858788898a', - 'ecb-tbl-128: I=7'), - ('b5bf946be19beb8db3983b5f4c6e8ddb', '131c886a57f8c2e713aba6955e2b55b5', - '8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-128: I=8'), - ('41321ee10e21bd907227c4450ff42324', 'd2ab7662df9b8c740210e5eeb61c199d', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2', - 'ecb-tbl-128: I=9'), - ('00a82f59c91c8486d12c0a80124f6089', '14c10554b2859c484cab5869bbe7c470', - 'b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', - 'ecb-tbl-128: I=10'), - ('7ce0fd076754691b4bbd9faf8a1372fe', 'db4d498f0a49cf55445d502c1f9ab3b5', - 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9da', - 'ecb-tbl-128: I=11'), - ('23605a8243d07764541bc5ad355b3129', '6d96fef7d66590a77a77bb2056667f7f', - 'dcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-128: I=12'), - ('12a8cfa23ea764fd876232b4e842bc44', '316fb68edba736c53e78477bf913725c', - 'f0f1f2f3f5f6f7f8fafbfcfdfe010002', - 'ecb-tbl-128: I=13'), - ('bcaf32415e8308b3723e5fdd853ccc80', '6936f2b93af8397fd3a771fc011c8c37', - '04050607090a0b0c0e0f101113141516', - 'ecb-tbl-128: I=14'), - ('89afae685d801ad747ace91fc49adde0', 'f3f92f7a9c59179c1fcc2c2ba0b082cd', - '2c2d2e2f31323334363738393b3c3d3e', - 'ecb-tbl-128: I=15'), - ('f521d07b484357c4a69e76124a634216', '6a95ea659ee3889158e7a9152ff04ebc', - '40414243454647484a4b4c4d4f505152', - 'ecb-tbl-128: I=16'), - ('3e23b3bc065bcc152407e23896d77783', '1959338344e945670678a5d432c90b93', - '54555657595a5b5c5e5f606163646566', - 'ecb-tbl-128: I=17'), - ('79f0fba002be1744670e7e99290d8f52', 'e49bddd2369b83ee66e6c75a1161b394', - '68696a6b6d6e6f70727374757778797a', - 'ecb-tbl-128: I=18'), - ('da23fe9d5bd63e1d72e3dafbe21a6c2a', 'd3388f19057ff704b70784164a74867d', - '7c7d7e7f81828384868788898b8c8d8e', - 'ecb-tbl-128: I=19'), - ('e3f5698ba90b6a022efd7db2c7e6c823', '23aa03e2d5e4cd24f3217e596480d1e1', - 'a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', - 'ecb-tbl-128: I=20'), - ('bdc2691d4f1b73d2700679c3bcbf9c6e', 'c84113d68b666ab2a50a8bdb222e91b9', - 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2', - 'ecb-tbl-128: I=21'), - ('ba74e02093217ee1ba1b42bd5624349a', 'ac02403981cd4340b507963db65cb7b6', - '08090a0b0d0e0f10121314151718191a', - 'ecb-tbl-128: I=22'), - ('b5c593b5851c57fbf8b3f57715e8f680', '8d1299236223359474011f6bf5088414', - '6c6d6e6f71727374767778797b7c7d7e', - 'ecb-tbl-128: I=23'), - ('3da9bd9cec072381788f9387c3bbf4ee', '5a1d6ab8605505f7977e55b9a54d9b90', - '80818283858687888a8b8c8d8f909192', - 'ecb-tbl-128: I=24'), - ('4197f3051121702ab65d316b3c637374', '72e9c2d519cf555e4208805aabe3b258', - '94959697999a9b9c9e9fa0a1a3a4a5a6', - 'ecb-tbl-128: I=25'), - ('9f46c62ec4f6ee3f6e8c62554bc48ab7', 'a8f3e81c4a23a39ef4d745dffe026e80', - 'a8a9aaabadaeafb0b2b3b4b5b7b8b9ba', - 'ecb-tbl-128: I=26'), - ('0220673fe9e699a4ebc8e0dbeb6979c8', '546f646449d31458f9eb4ef5483aee6c', - 'bcbdbebfc1c2c3c4c6c7c8c9cbcccdce', - 'ecb-tbl-128: I=27'), - ('b2b99171337ded9bc8c2c23ff6f18867', '4dbe4bc84ac797c0ee4efb7f1a07401c', - 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2', - 'ecb-tbl-128: I=28'), - ('a7facf4e301e984e5efeefd645b23505', '25e10bfb411bbd4d625ac8795c8ca3b3', - 'e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', - 'ecb-tbl-128: I=29'), - ('f7c762e4a9819160fd7acfb6c4eedcdd', '315637405054ec803614e43def177579', - 'f8f9fafbfdfefe00020304050708090a', - 'ecb-tbl-128: I=30'), - ('9b64fc21ea08709f4915436faa70f1be', '60c5bc8a1410247295c6386c59e572a8', - '0c0d0e0f11121314161718191b1c1d1e', - 'ecb-tbl-128: I=31'), - ('52af2c3de07ee6777f55a4abfc100b3f', '01366fc8ca52dfe055d6a00a76471ba6', - '20212223252627282a2b2c2d2f303132', - 'ecb-tbl-128: I=32'), - ('2fca001224386c57aa3f968cbe2c816f', 'ecc46595516ec612449c3f581e7d42ff', - '34353637393a3b3c3e3f404143444546', - 'ecb-tbl-128: I=33'), - ('4149c73658a4a9c564342755ee2c132f', '6b7ffe4c602a154b06ee9c7dab5331c9', - '48494a4b4d4e4f50525354555758595a', - 'ecb-tbl-128: I=34'), - ('af60005a00a1772f7c07a48a923c23d2', '7da234c14039a240dd02dd0fbf84eb67', - '5c5d5e5f61626364666768696b6c6d6e', - 'ecb-tbl-128: I=35'), - ('6fccbc28363759914b6f0280afaf20c6', 'c7dc217d9e3604ffe7e91f080ecd5a3a', - '70717273757677787a7b7c7d7f808182', - 'ecb-tbl-128: I=36'), - ('7d82a43ddf4fefa2fc5947499884d386', '37785901863f5c81260ea41e7580cda5', - '84858687898a8b8c8e8f909193949596', - 'ecb-tbl-128: I=37'), - ('5d5a990eaab9093afe4ce254dfa49ef9', 'a07b9338e92ed105e6ad720fccce9fe4', - '98999a9b9d9e9fa0a2a3a4a5a7a8a9aa', - 'ecb-tbl-128: I=38'), - ('4cd1e2fd3f4434b553aae453f0ed1a02', 'ae0fb9722418cc21a7da816bbc61322c', - 'acadaeafb1b2b3b4b6b7b8b9bbbcbdbe', - 'ecb-tbl-128: I=39'), - ('5a2c9a9641d4299125fa1b9363104b5e', 'c826a193080ff91ffb21f71d3373c877', - 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2', - 'ecb-tbl-128: I=40'), - ('b517fe34c0fa217d341740bfd4fe8dd4', '1181b11b0e494e8d8b0aa6b1d5ac2c48', - 'd4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', - 'ecb-tbl-128: I=41'), - ('014baf2278a69d331d5180103643e99a', '6743c3d1519ab4f2cd9a78ab09a511bd', - 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fa', - 'ecb-tbl-128: I=42'), - ('b529bd8164f20d0aa443d4932116841c', 'dc55c076d52bacdf2eefd952946a439d', - 'fcfdfeff01020304060708090b0c0d0e', - 'ecb-tbl-128: I=43'), - ('2e596dcbb2f33d4216a1176d5bd1e456', '711b17b590ffc72b5c8e342b601e8003', - '10111213151617181a1b1c1d1f202122', - 'ecb-tbl-128: I=44'), - ('7274a1ea2b7ee2424e9a0e4673689143', '19983bb0950783a537e1339f4aa21c75', - '24252627292a2b2c2e2f303133343536', - 'ecb-tbl-128: I=45'), - ('ae20020bd4f13e9d90140bee3b5d26af', '3ba7762e15554169c0f4fa39164c410c', - '38393a3b3d3e3f40424344454748494a', - 'ecb-tbl-128: I=46'), - ('baac065da7ac26e855e79c8849d75a02', 'a0564c41245afca7af8aa2e0e588ea89', - '4c4d4e4f51525354565758595b5c5d5e', - 'ecb-tbl-128: I=47'), - ('7c917d8d1d45fab9e2540e28832540cc', '5e36a42a2e099f54ae85ecd92e2381ed', - '60616263656667686a6b6c6d6f707172', - 'ecb-tbl-128: I=48'), - ('bde6f89e16daadb0e847a2a614566a91', '770036f878cd0f6ca2268172f106f2fe', - '74757677797a7b7c7e7f808183848586', - 'ecb-tbl-128: I=49'), - ('c9de163725f1f5be44ebb1db51d07fbc', '7e4e03908b716116443ccf7c94e7c259', - '88898a8b8d8e8f90929394959798999a', - 'ecb-tbl-128: I=50'), - ('3af57a58f0c07dffa669572b521e2b92', '482735a48c30613a242dd494c7f9185d', - '9c9d9e9fa1a2a3a4a6a7a8a9abacadae', - 'ecb-tbl-128: I=51'), - ('3d5ebac306dde4604f1b4fbbbfcdae55', 'b4c0f6c9d4d7079addf9369fc081061d', - 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2', - 'ecb-tbl-128: I=52'), - ('c2dfa91bceb76a1183c995020ac0b556', 'd5810fe0509ac53edcd74f89962e6270', - 'c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', - 'ecb-tbl-128: I=53'), - ('c70f54305885e9a0746d01ec56c8596b', '03f17a16b3f91848269ecdd38ebb2165', - 'd8d9dadbdddedfe0e2e3e4e5e7e8e9ea', - 'ecb-tbl-128: I=54'), - ('c4f81b610e98012ce000182050c0c2b2', 'da1248c3180348bad4a93b4d9856c9df', - 'ecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', - 'ecb-tbl-128: I=55'), - ('eaab86b1d02a95d7404eff67489f97d4', '3d10d7b63f3452c06cdf6cce18be0c2c', - '00010203050607080a0b0c0d0f101112', - 'ecb-tbl-128: I=56'), - ('7c55bdb40b88870b52bec3738de82886', '4ab823e7477dfddc0e6789018fcb6258', - '14151617191a1b1c1e1f202123242526', - 'ecb-tbl-128: I=57'), - ('ba6eaa88371ff0a3bd875e3f2a975ce0', 'e6478ba56a77e70cfdaa5c843abde30e', - '28292a2b2d2e2f30323334353738393a', - 'ecb-tbl-128: I=58'), - ('08059130c4c24bd30cf0575e4e0373dc', '1673064895fbeaf7f09c5429ff75772d', - '3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-128: I=59'), - ('9a8eab004ef53093dfcf96f57e7eda82', '4488033ae9f2efd0ca9383bfca1a94e9', - '50515253555657585a5b5c5d5f606162', - 'ecb-tbl-128: I=60'), - ('0745b589e2400c25f117b1d796c28129', '978f3b8c8f9d6f46626cac3c0bcb9217', - '64656667696a6b6c6e6f707173747576', - 'ecb-tbl-128: I=61'), - ('2f1777781216cec3f044f134b1b92bbe', 'e08c8a7e582e15e5527f1d9e2eecb236', - '78797a7b7d7e7f80828384858788898a', - 'ecb-tbl-128: I=62'), - ('353a779ffc541b3a3805d90ce17580fc', 'cec155b76ac5ffda4cf4f9ca91e49a7a', - '8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-128: I=63'), - ('1a1eae4415cefcf08c4ac1c8f68bea8f', 'd5ac7165763225dd2a38cdc6862c29ad', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2', - 'ecb-tbl-128: I=64'), - ('e6e7e4e5b0b3b2b5d4d5aaab16111013', '03680fe19f7ce7275452020be70e8204', - 'b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', - 'ecb-tbl-128: I=65'), - ('f8f9fafbfbf8f9e677767170efe0e1e2', '461df740c9781c388e94bb861ceb54f6', - 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9da', - 'ecb-tbl-128: I=66'), - ('63626160a1a2a3a445444b4a75727370', '451bd60367f96483042742219786a074', - 'dcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-128: I=67'), - ('717073720605040b2d2c2b2a05fafbf9', 'e4dfa42671a02e57ef173b85c0ea9f2b', - 'f0f1f2f3f5f6f7f8fafbfcfdfe010002', - 'ecb-tbl-128: I=68'), - ('78797a7beae9e8ef3736292891969794', 'ed11b89e76274282227d854700a78b9e', - '04050607090a0b0c0e0f101113141516', - 'ecb-tbl-128: I=69'), - ('838281803231300fdddcdbdaa0afaead', '433946eaa51ea47af33895f2b90b3b75', - '18191a1b1d1e1f20222324252728292a', - 'ecb-tbl-128: I=70'), - ('18191a1bbfbcbdba75747b7a7f78797a', '6bc6d616a5d7d0284a5910ab35022528', - '2c2d2e2f31323334363738393b3c3d3e', - 'ecb-tbl-128: I=71'), - ('848586879b989996a3a2a5a4849b9a99', 'd2a920ecfe919d354b5f49eae9719c98', - '40414243454647484a4b4c4d4f505152', - 'ecb-tbl-128: I=72'), - ('0001020322212027cacbf4f551565754', '3a061b17f6a92885efbd0676985b373d', - '54555657595a5b5c5e5f606163646566', - 'ecb-tbl-128: I=73'), - ('cecfcccdafacadb2515057564a454447', 'fadeec16e33ea2f4688499d157e20d8f', - '68696a6b6d6e6f70727374757778797a', - 'ecb-tbl-128: I=74'), - ('92939091cdcecfc813121d1c80878685', '5cdefede59601aa3c3cda36fa6b1fa13', - '7c7d7e7f81828384868788898b8c8d8e', - 'ecb-tbl-128: I=75'), - ('d2d3d0d16f6c6d6259585f5ed1eeefec', '9574b00039844d92ebba7ee8719265f8', - '90919293959697989a9b9c9d9fa0a1a2', - 'ecb-tbl-128: I=76'), - ('acadaeaf878485820f0e1110d5d2d3d0', '9a9cf33758671787e5006928188643fa', - 'a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', - 'ecb-tbl-128: I=77'), - ('9091929364676619e6e7e0e1757a7b78', '2cddd634c846ba66bb46cbfea4a674f9', - 'b8b9babbbdbebfc0c2c3c4c5c7c8c9ca', - 'ecb-tbl-128: I=78'), - ('babbb8b98a89888f74757a7b92959497', 'd28bae029393c3e7e26e9fafbbb4b98f', - 'cccdcecfd1d2d3d4d6d7d8d9dbdcddde', - 'ecb-tbl-128: I=79'), - ('8d8c8f8e6e6d6c633b3a3d3ccad5d4d7', 'ec27529b1bee0a9ab6a0d73ebc82e9b7', - 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2', - 'ecb-tbl-128: I=80'), - ('86878485010203040808f7f767606162', '3cb25c09472aff6ee7e2b47ccd7ccb17', - 'f4f5f6f7f9fafbfcfefe010103040506', - 'ecb-tbl-128: I=81'), - ('8e8f8c8d656667788a8b8c8d010e0f0c', 'dee33103a7283370d725e44ca38f8fe5', - '08090a0b0d0e0f10121314151718191a', - 'ecb-tbl-128: I=82'), - ('c8c9cacb858687807a7b7475e7e0e1e2', '27f9bcd1aac64bffc11e7815702c1a69', - '1c1d1e1f21222324262728292b2c2d2e', - 'ecb-tbl-128: I=83'), - ('6d6c6f6e5053525d8c8d8a8badd2d3d0', '5df534ffad4ed0749a9988e9849d0021', - '30313233353637383a3b3c3d3f404142', - 'ecb-tbl-128: I=84'), - ('28292a2b393a3b3c0607181903040506', 'a48bee75db04fb60ca2b80f752a8421b', - '44454647494a4b4c4e4f505153545556', - 'ecb-tbl-128: I=85'), - ('a5a4a7a6b0b3b28ddbdadddcbdb2b3b0', '024c8cf70bc86ee5ce03678cb7af45f9', - '58595a5b5d5e5f60626364656768696a', - 'ecb-tbl-128: I=86'), - ('323330316467666130313e3f2c2b2a29', '3c19ac0f8a3a3862ce577831301e166b', - '6c6d6e6f71727374767778797b7c7d7e', - 'ecb-tbl-128: I=87'), - ('27262524080b0a05171611100b141516', 'c5e355b796a57421d59ca6be82e73bca', - '80818283858687888a8b8c8d8f909192', - 'ecb-tbl-128: I=88'), - ('040506074142434435340b0aa3a4a5a6', 'd94033276417abfb05a69d15b6e386e2', - '94959697999a9b9c9e9fa0a1a3a4a5a6', - 'ecb-tbl-128: I=89'), - ('242526271112130c61606766bdb2b3b0', '24b36559ea3a9b9b958fe6da3e5b8d85', - 'a8a9aaabadaeafb0b2b3b4b5b7b8b9ba', - 'ecb-tbl-128: I=90'), - ('4b4a4948252627209e9f9091cec9c8cb', '20fd4feaa0e8bf0cce7861d74ef4cb72', - 'bcbdbebfc1c2c3c4c6c7c8c9cbcccdce', - 'ecb-tbl-128: I=91'), - ('68696a6b6665646b9f9e9998d9e6e7e4', '350e20d5174277b9ec314c501570a11d', - 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2', - 'ecb-tbl-128: I=92'), - ('34353637c5c6c7c0f0f1eeef7c7b7a79', '87a29d61b7c604d238fe73045a7efd57', - 'e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', - 'ecb-tbl-128: I=93'), - ('32333031c2c1c13f0d0c0b0a050a0b08', '2c3164c1cc7d0064816bdc0faa362c52', - 'f8f9fafbfdfefe00020304050708090a', - 'ecb-tbl-128: I=94'), - ('cdcccfcebebdbcbbabaaa5a4181f1e1d', '195fe5e8a05a2ed594f6e4400eee10b3', - '0c0d0e0f11121314161718191b1c1d1e', - 'ecb-tbl-128: I=95'), - ('212023223635343ba0a1a6a7445b5a59', 'e4663df19b9a21a5a284c2bd7f905025', - '20212223252627282a2b2c2d2f303132', - 'ecb-tbl-128: I=96'), - ('0e0f0c0da8abaaad2f2e515002050407', '21b88714cfb4e2a933bd281a2c4743fd', - '34353637393a3b3c3e3f404143444546', - 'ecb-tbl-128: I=97'), - ('070605042a2928378e8f8889bdb2b3b0', 'cbfc3980d704fd0fc54378ab84e17870', - '48494a4b4d4e4f50525354555758595a', - 'ecb-tbl-128: I=98'), - ('cbcac9c893909196a9a8a7a6a5a2a3a0', 'bc5144baa48bdeb8b63e22e03da418ef', - '5c5d5e5f61626364666768696b6c6d6e', - 'ecb-tbl-128: I=99'), - ('80818283c1c2c3cc9c9d9a9b0cf3f2f1', '5a1dbaef1ee2984b8395da3bdffa3ccc', - '70717273757677787a7b7c7d7f808182', - 'ecb-tbl-128: I=100'), - ('1213101125262720fafbe4e5b1b6b7b4', 'f0b11cd0729dfcc80cec903d97159574', - '84858687898a8b8c8e8f909193949596', - 'ecb-tbl-128: I=101'), - ('7f7e7d7c3033320d97969190222d2c2f', '9f95314acfddc6d1914b7f19a9cc8209', - '98999a9b9d9e9fa0a2a3a4a5a7a8a9aa', - 'ecb-tbl-128: I=102'), - ('4e4f4c4d484b4a4d81808f8e53545556', '595736f6f0f70914a94e9e007f022519', - 'acadaeafb1b2b3b4b6b7b8b9bbbcbdbe', - 'ecb-tbl-128: I=103'), - ('dcdddedfb0b3b2bd15141312a1bebfbc', '1f19f57892cae586fcdfb4c694deb183', - 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2', - 'ecb-tbl-128: I=104'), - ('93929190282b2a2dc4c5fafb92959497', '540700ee1f6f3dab0b3eddf6caee1ef5', - 'd4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', - 'ecb-tbl-128: I=105'), - ('f5f4f7f6c4c7c6d9373631307e717073', '14a342a91019a331687a2254e6626ca2', - 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fa', - 'ecb-tbl-128: I=106'), - ('93929190b6b5b4b364656a6b05020300', '7b25f3c3b2eea18d743ef283140f29ff', - 'fcfdfeff01020304060708090b0c0d0e', - 'ecb-tbl-128: I=107'), - ('babbb8b90d0e0f00a4a5a2a3043b3a39', '46c2587d66e5e6fa7f7ca6411ad28047', - '10111213151617181a1b1c1d1f202122', - 'ecb-tbl-128: I=108'), - ('d8d9dadb7f7c7d7a10110e0f787f7e7d', '09470e72229d954ed5ee73886dfeeba9', - '24252627292a2b2c2e2f303133343536', - 'ecb-tbl-128: I=109'), - ('fefffcfdefeced923b3a3d3c6768696a', 'd77c03de92d4d0d79ef8d4824ef365eb', - '38393a3b3d3e3f40424344454748494a', - 'ecb-tbl-128: I=110'), - ('d6d7d4d58a89888f96979899a5a2a3a0', '1d190219f290e0f1715d152d41a23593', - '4c4d4e4f51525354565758595b5c5d5e', - 'ecb-tbl-128: I=111'), - ('18191a1ba8abaaa5303136379b848586', 'a2cd332ce3a0818769616292e87f757b', - '60616263656667686a6b6c6d6f707172', - 'ecb-tbl-128: I=112'), - ('6b6a6968a4a7a6a1d6d72829b0b7b6b5', 'd54afa6ce60fbf9341a3690e21385102', - '74757677797a7b7c7e7f808183848586', - 'ecb-tbl-128: I=113'), - ('000102038a89889755545352a6a9a8ab', '06e5c364ded628a3f5e05e613e356f46', - '88898a8b8d8e8f90929394959798999a', - 'ecb-tbl-128: I=114'), - ('2d2c2f2eb3b0b1b6b6b7b8b9f2f5f4f7', 'eae63c0e62556dac85d221099896355a', - '9c9d9e9fa1a2a3a4a6a7a8a9abacadae', - 'ecb-tbl-128: I=115'), - ('979695943536373856575051e09f9e9d', '1fed060e2c6fc93ee764403a889985a2', - 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2', - 'ecb-tbl-128: I=116'), - ('a4a5a6a7989b9a9db1b0afae7a7d7c7f', 'c25235c1a30fdec1c7cb5c5737b2a588', - 'c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', - 'ecb-tbl-128: I=117'), - ('c1c0c3c2686b6a55a8a9aeafeae5e4e7', '796dbef95147d4d30873ad8b7b92efc0', - 'd8d9dadbdddedfe0e2e3e4e5e7e8e9ea', - 'ecb-tbl-128: I=118'), - ('c1c0c3c2141716118c8d828364636261', 'cbcf0fb34d98d0bd5c22ce37211a46bf', - 'ecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', - 'ecb-tbl-128: I=119'), - ('93929190cccfcec196979091e0fffefd', '94b44da6466126cafa7c7fd09063fc24', - '00010203050607080a0b0c0d0f101112', - 'ecb-tbl-128: I=120'), - ('b4b5b6b7f9fafbfc25241b1a6e69686b', 'd78c5b5ebf9b4dbda6ae506c5074c8fe', - '14151617191a1b1c1e1f202123242526', - 'ecb-tbl-128: I=121'), - ('868784850704051ac7c6c1c08788898a', '6c27444c27204b043812cf8cf95f9769', - '28292a2b2d2e2f30323334353738393a', - 'ecb-tbl-128: I=122'), - ('f4f5f6f7aaa9a8affdfcf3f277707172', 'be94524ee5a2aa50bba8b75f4c0aebcf', - '3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-128: I=123'), - ('d3d2d1d00605040bc3c2c5c43e010003', 'a0aeaae91ba9f31f51aeb3588cf3a39e', - '50515253555657585a5b5c5d5f606162', - 'ecb-tbl-128: I=124'), - ('73727170424140476a6b74750d0a0b08', '275297779c28266ef9fe4c6a13c08488', - '64656667696a6b6c6e6f707173747576', - 'ecb-tbl-128: I=125'), - ('c2c3c0c10a0908f754555253a1aeafac', '86523d92bb8672cb01cf4a77fd725882', - '78797a7b7d7e7f80828384858788898a', - 'ecb-tbl-128: I=126'), - ('6d6c6f6ef8fbfafd82838c8df8fffefd', '4b8327640e9f33322a04dd96fcbf9a36', - '8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-128: I=127'), - ('f5f4f7f684878689a6a7a0a1d2cdcccf', 'ce52af650d088ca559425223f4d32694', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2', - 'ecb-tbl-128: I=128'), - - # ecb_tbl.txt, KEYSIZE=192 - ('2d33eef2c0430a8a9ebf45e809c40bb6', 'dff4945e0336df4c1c56bc700eff837f', - '00010203050607080a0b0c0d0f10111214151617191a1b1c', - 'ecb-tbl-192: I=1'), - ('6aa375d1fa155a61fb72353e0a5a8756', 'b6fddef4752765e347d5d2dc196d1252', - '1e1f20212324252628292a2b2d2e2f30323334353738393a', - 'ecb-tbl-192: I=2'), - ('bc3736518b9490dcb8ed60eb26758ed4', 'd23684e3d963b3afcf1a114aca90cbd6', - '3c3d3e3f41424344464748494b4c4d4e5051525355565758', - 'ecb-tbl-192: I=3'), - ('aa214402b46cffb9f761ec11263a311e', '3a7ac027753e2a18c2ceab9e17c11fd0', - '5a5b5c5d5f60616264656667696a6b6c6e6f707173747576', - 'ecb-tbl-192: I=4'), - ('02aea86e572eeab66b2c3af5e9a46fd6', '8f6786bd007528ba26603c1601cdd0d8', - '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394', - 'ecb-tbl-192: I=5'), - ('e2aef6acc33b965c4fa1f91c75ff6f36', 'd17d073b01e71502e28b47ab551168b3', - '969798999b9c9d9ea0a1a2a3a5a6a7a8aaabacadafb0b1b2', - 'ecb-tbl-192: I=6'), - ('0659df46427162b9434865dd9499f91d', 'a469da517119fab95876f41d06d40ffa', - 'b4b5b6b7b9babbbcbebfc0c1c3c4c5c6c8c9cacbcdcecfd0', - 'ecb-tbl-192: I=7'), - ('49a44239c748feb456f59c276a5658df', '6091aa3b695c11f5c0b6ad26d3d862ff', - 'd2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-192: I=8'), - ('66208f6e9d04525bdedb2733b6a6be37', '70f9e67f9f8df1294131662dc6e69364', - 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c', - 'ecb-tbl-192: I=9'), - ('3393f8dfc729c97f5480b950bc9666b0', 'd154dcafad8b207fa5cbc95e9996b559', - '0e0f10111314151618191a1b1d1e1f20222324252728292a', - 'ecb-tbl-192: I=10'), - ('606834c8ce063f3234cf1145325dbd71', '4934d541e8b46fa339c805a7aeb9e5da', - '2c2d2e2f31323334363738393b3c3d3e4041424345464748', - 'ecb-tbl-192: I=11'), - ('fec1c04f529bbd17d8cecfcc4718b17f', '62564c738f3efe186e1a127a0c4d3c61', - '4a4b4c4d4f50515254555657595a5b5c5e5f606163646566', - 'ecb-tbl-192: I=12'), - ('32df99b431ed5dc5acf8caf6dc6ce475', '07805aa043986eb23693e23bef8f3438', - '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384', - 'ecb-tbl-192: I=13'), - ('7fdc2b746f3f665296943b83710d1f82', 'df0b4931038bade848dee3b4b85aa44b', - '868788898b8c8d8e90919293959697989a9b9c9d9fa0a1a2', - 'ecb-tbl-192: I=14'), - ('8fba1510a3c5b87e2eaa3f7a91455ca2', '592d5fded76582e4143c65099309477c', - 'a4a5a6a7a9aaabacaeafb0b1b3b4b5b6b8b9babbbdbebfc0', - 'ecb-tbl-192: I=15'), - ('2c9b468b1c2eed92578d41b0716b223b', 'c9b8d6545580d3dfbcdd09b954ed4e92', - 'c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde', - 'ecb-tbl-192: I=16'), - ('0a2bbf0efc6bc0034f8a03433fca1b1a', '5dccd5d6eb7c1b42acb008201df707a0', - 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfc', - 'ecb-tbl-192: I=17'), - ('25260e1f31f4104d387222e70632504b', 'a2a91682ffeb6ed1d34340946829e6f9', - 'fefe01010304050608090a0b0d0e0f10121314151718191a', - 'ecb-tbl-192: I=18'), - ('c527d25a49f08a5228d338642ae65137', 'e45d185b797000348d9267960a68435d', - '1c1d1e1f21222324262728292b2c2d2e3031323335363738', - 'ecb-tbl-192: I=19'), - ('3b49fc081432f5890d0e3d87e884a69e', '45e060dae5901cda8089e10d4f4c246b', - '3a3b3c3d3f40414244454647494a4b4c4e4f505153545556', - 'ecb-tbl-192: I=20'), - ('d173f9ed1e57597e166931df2754a083', 'f6951afacc0079a369c71fdcff45df50', - '58595a5b5d5e5f60626364656768696a6c6d6e6f71727374', - 'ecb-tbl-192: I=21'), - ('8c2b7cafa5afe7f13562daeae1adede0', '9e95e00f351d5b3ac3d0e22e626ddad6', - '767778797b7c7d7e80818283858687888a8b8c8d8f909192', - 'ecb-tbl-192: I=22'), - ('aaf4ec8c1a815aeb826cab741339532c', '9cb566ff26d92dad083b51fdc18c173c', - '94959697999a9b9c9e9fa0a1a3a4a5a6a8a9aaabadaeafb0', - 'ecb-tbl-192: I=23'), - ('40be8c5d9108e663f38f1a2395279ecf', 'c9c82766176a9b228eb9a974a010b4fb', - 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebec', - 'ecb-tbl-192: I=24'), - ('0c8ad9bc32d43e04716753aa4cfbe351', 'd8e26aa02945881d5137f1c1e1386e88', - '2a2b2c2d2f30313234353637393a3b3c3e3f404143444546', - 'ecb-tbl-192: I=25'), - ('1407b1d5f87d63357c8dc7ebbaebbfee', 'c0e024ccd68ff5ffa4d139c355a77c55', - '48494a4b4d4e4f50525354555758595a5c5d5e5f61626364', - 'ecb-tbl-192: I=26'), - ('e62734d1ae3378c4549e939e6f123416', '0b18b3d16f491619da338640df391d43', - '84858687898a8b8c8e8f90919394959698999a9b9d9e9fa0', - 'ecb-tbl-192: I=27'), - ('5a752cff2a176db1a1de77f2d2cdee41', 'dbe09ac8f66027bf20cb6e434f252efc', - 'a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe', - 'ecb-tbl-192: I=28'), - ('a9c8c3a4eabedc80c64730ddd018cd88', '6d04e5e43c5b9cbe05feb9606b6480fe', - 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdc', - 'ecb-tbl-192: I=29'), - ('ee9b3dbbdb86180072130834d305999a', 'dd1d6553b96be526d9fee0fbd7176866', - '1a1b1c1d1f20212224252627292a2b2c2e2f303133343536', - 'ecb-tbl-192: I=30'), - ('a7fa8c3586b8ebde7568ead6f634a879', '0260ca7e3f979fd015b0dd4690e16d2a', - '38393a3b3d3e3f40424344454748494a4c4d4e4f51525354', - 'ecb-tbl-192: I=31'), - ('37e0f4a87f127d45ac936fe7ad88c10a', '9893734de10edcc8a67c3b110b8b8cc6', - '929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae', - 'ecb-tbl-192: I=32'), - ('3f77d8b5d92bac148e4e46f697a535c5', '93b30b750516b2d18808d710c2ee84ef', - '464748494b4c4d4e50515253555657585a5b5c5d5f606162', - 'ecb-tbl-192: I=33'), - ('d25ebb686c40f7e2c4da1014936571ca', '16f65fa47be3cb5e6dfe7c6c37016c0e', - '828384858788898a8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-192: I=34'), - ('4f1c769d1e5b0552c7eca84dea26a549', 'f3847210d5391e2360608e5acb560581', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbc', - 'ecb-tbl-192: I=35'), - ('8548e2f882d7584d0fafc54372b6633a', '8754462cd223366d0753913e6af2643d', - 'bebfc0c1c3c4c5c6c8c9cacbcdcecfd0d2d3d4d5d7d8d9da', - 'ecb-tbl-192: I=36'), - ('87d7a336cb476f177cd2a51af2a62cdf', '1ea20617468d1b806a1fd58145462017', - 'dcdddedfe1e2e3e4e6e7e8e9ebecedeef0f1f2f3f5f6f7f8', - 'ecb-tbl-192: I=37'), - ('03b1feac668c4e485c1065dfc22b44ee', '3b155d927355d737c6be9dda60136e2e', - 'fafbfcfdfe01000204050607090a0b0c0e0f101113141516', - 'ecb-tbl-192: I=38'), - ('bda15e66819fa72d653a6866aa287962', '26144f7b66daa91b6333dbd3850502b3', - '18191a1b1d1e1f20222324252728292a2c2d2e2f31323334', - 'ecb-tbl-192: I=39'), - ('4d0c7a0d2505b80bf8b62ceb12467f0a', 'e4f9a4ab52ced8134c649bf319ebcc90', - '363738393b3c3d3e40414243454647484a4b4c4d4f505152', - 'ecb-tbl-192: I=40'), - ('626d34c9429b37211330986466b94e5f', 'b9ddd29ac6128a6cab121e34a4c62b36', - '54555657595a5b5c5e5f60616364656668696a6b6d6e6f70', - 'ecb-tbl-192: I=41'), - ('333c3e6bf00656b088a17e5ff0e7f60a', '6fcddad898f2ce4eff51294f5eaaf5c9', - '727374757778797a7c7d7e7f81828384868788898b8c8d8e', - 'ecb-tbl-192: I=42'), - ('687ed0cdc0d2a2bc8c466d05ef9d2891', 'c9a6fe2bf4028080bea6f7fc417bd7e3', - '90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabac', - 'ecb-tbl-192: I=43'), - ('487830e78cc56c1693e64b2a6660c7b6', '6a2026846d8609d60f298a9c0673127f', - 'aeafb0b1b3b4b5b6b8b9babbbdbebfc0c2c3c4c5c7c8c9ca', - 'ecb-tbl-192: I=44'), - ('7a48d6b7b52b29392aa2072a32b66160', '2cb25c005e26efea44336c4c97a4240b', - 'cccdcecfd1d2d3d4d6d7d8d9dbdcdddee0e1e2e3e5e6e7e8', - 'ecb-tbl-192: I=45'), - ('907320e64c8c5314d10f8d7a11c8618d', '496967ab8680ddd73d09a0e4c7dcc8aa', - 'eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506', - 'ecb-tbl-192: I=46'), - ('b561f2ca2d6e65a4a98341f3ed9ff533', 'd5af94de93487d1f3a8c577cb84a66a4', - '08090a0b0d0e0f10121314151718191a1c1d1e1f21222324', - 'ecb-tbl-192: I=47'), - ('df769380d212792d026f049e2e3e48ef', '84bdac569cae2828705f267cc8376e90', - '262728292b2c2d2e30313233353637383a3b3c3d3f404142', - 'ecb-tbl-192: I=48'), - ('79f374bc445bdabf8fccb8843d6054c6', 'f7401dda5ad5ab712b7eb5d10c6f99b6', - '44454647494a4b4c4e4f50515354555658595a5b5d5e5f60', - 'ecb-tbl-192: I=49'), - ('4e02f1242fa56b05c68dbae8fe44c9d6', '1c9d54318539ebd4c3b5b7e37bf119f0', - '626364656768696a6c6d6e6f71727374767778797b7c7d7e', - 'ecb-tbl-192: I=50'), - ('cf73c93cbff57ac635a6f4ad2a4a1545', 'aca572d65fb2764cffd4a6eca090ea0d', - '80818283858687888a8b8c8d8f90919294959697999a9b9c', - 'ecb-tbl-192: I=51'), - ('9923548e2875750725b886566784c625', '36d9c627b8c2a886a10ccb36eae3dfbb', - '9e9fa0a1a3a4a5a6a8a9aaabadaeafb0b2b3b4b5b7b8b9ba', - 'ecb-tbl-192: I=52'), - ('4888336b723a022c9545320f836a4207', '010edbf5981e143a81d646e597a4a568', - 'bcbdbebfc1c2c3c4c6c7c8c9cbcccdced0d1d2d3d5d6d7d8', - 'ecb-tbl-192: I=53'), - ('f84d9a5561b0608b1160dee000c41ba8', '8db44d538dc20cc2f40f3067fd298e60', - 'dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', - 'ecb-tbl-192: I=54'), - ('c23192a0418e30a19b45ae3e3625bf22', '930eb53bc71e6ac4b82972bdcd5aafb3', - 'f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314', - 'ecb-tbl-192: I=55'), - ('b84e0690b28b0025381ad82a15e501a7', '6c42a81edcbc9517ccd89c30c95597b4', - '161718191b1c1d1e20212223252627282a2b2c2d2f303132', - 'ecb-tbl-192: I=56'), - ('acef5e5c108876c4f06269f865b8f0b0', 'da389847ad06df19d76ee119c71e1dd3', - '34353637393a3b3c3e3f40414344454648494a4b4d4e4f50', - 'ecb-tbl-192: I=57'), - ('0f1b3603e0f5ddea4548246153a5e064', 'e018fdae13d3118f9a5d1a647a3f0462', - '525354555758595a5c5d5e5f61626364666768696b6c6d6e', - 'ecb-tbl-192: I=58'), - ('fbb63893450d42b58c6d88cd3c1809e3', '2aa65db36264239d3846180fabdfad20', - '70717273757677787a7b7c7d7f80818284858687898a8b8c', - 'ecb-tbl-192: I=59'), - ('4bef736df150259dae0c91354e8a5f92', '1472163e9a4f780f1ceb44b07ecf4fdb', - '8e8f90919394959698999a9b9d9e9fa0a2a3a4a5a7a8a9aa', - 'ecb-tbl-192: I=60'), - ('7d2d46242056ef13d3c3fc93c128f4c7', 'c8273fdc8f3a9f72e91097614b62397c', - 'acadaeafb1b2b3b4b6b7b8b9bbbcbdbec0c1c2c3c5c6c7c8', - 'ecb-tbl-192: I=61'), - ('e9c1ba2df415657a256edb33934680fd', '66c8427dcd733aaf7b3470cb7d976e3f', - 'cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', - 'ecb-tbl-192: I=62'), - ('e23ee277b0aa0a1dfb81f7527c3514f1', '146131cb17f1424d4f8da91e6f80c1d0', - 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304', - 'ecb-tbl-192: I=63'), - ('3e7445b0b63caaf75e4a911e12106b4c', '2610d0ad83659081ae085266a88770dc', - '060708090b0c0d0e10111213151617181a1b1c1d1f202122', - 'ecb-tbl-192: I=64'), - ('767774752023222544455a5be6e1e0e3', '38a2b5a974b0575c5d733917fb0d4570', - '24252627292a2b2c2e2f30313334353638393a3b3d3e3f40', - 'ecb-tbl-192: I=65'), - ('72737475717e7f7ce9e8ebea696a6b6c', 'e21d401ebc60de20d6c486e4f39a588b', - '424344454748494a4c4d4e4f51525354565758595b5c5d5e', - 'ecb-tbl-192: I=66'), - ('dfdedddc25262728c9c8cfcef1eeefec', 'e51d5f88c670b079c0ca1f0c2c4405a2', - '60616263656667686a6b6c6d6f70717274757677797a7b7c', - 'ecb-tbl-192: I=67'), - ('fffe0100707776755f5e5d5c7675746b', '246a94788a642fb3d1b823c8762380c8', - '7e7f80818384858688898a8b8d8e8f90929394959798999a', - 'ecb-tbl-192: I=68'), - ('e0e1e2e3424140479f9e9190292e2f2c', 'b80c391c5c41a4c3b30c68e0e3d7550f', - '9c9d9e9fa1a2a3a4a6a7a8a9abacadaeb0b1b2b3b5b6b7b8', - 'ecb-tbl-192: I=69'), - ('2120272690efeeed3b3a39384e4d4c4b', 'b77c4754fc64eb9a1154a9af0bb1f21c', - 'babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', - 'ecb-tbl-192: I=70'), - ('ecedeeef5350516ea1a0a7a6a3acadae', 'fb554de520d159a06bf219fc7f34a02f', - 'd8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4', - 'ecb-tbl-192: I=71'), - ('32333c3d25222320e9e8ebeacecdccc3', 'a89fba152d76b4927beed160ddb76c57', - 'f6f7f8f9fbfcfdfe00010203050607080a0b0c0d0f101112', - 'ecb-tbl-192: I=72'), - ('40414243626160678a8bb4b511161714', '5676eab4a98d2e8473b3f3d46424247c', - '14151617191a1b1c1e1f20212324252628292a2b2d2e2f30', - 'ecb-tbl-192: I=73'), - ('94959293f5fafbf81f1e1d1c7c7f7e79', '4e8f068bd7ede52a639036ec86c33568', - '323334353738393a3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-192: I=74'), - ('bebfbcbd191a1b14cfcec9c8546b6a69', 'f0193c4d7aff1791ee4c07eb4a1824fc', - '50515253555657585a5b5c5d5f60616264656667696a6b6c', - 'ecb-tbl-192: I=75'), - ('2c2d3233898e8f8cbbbab9b8333031ce', 'ac8686eeca9ba761afe82d67b928c33f', - '6e6f70717374757678797a7b7d7e7f80828384858788898a', - 'ecb-tbl-192: I=76'), - ('84858687bfbcbdba37363938fdfafbf8', '5faf8573e33b145b6a369cd3606ab2c9', - '8c8d8e8f91929394969798999b9c9d9ea0a1a2a3a5a6a7a8', - 'ecb-tbl-192: I=77'), - ('828384857669686b909192930b08090e', '31587e9944ab1c16b844ecad0df2e7da', - 'aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', - 'ecb-tbl-192: I=78'), - ('bebfbcbd9695948b707176779e919093', 'd017fecd91148aba37f6f3068aa67d8a', - 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4', - 'ecb-tbl-192: I=79'), - ('8b8a85846067666521202322d0d3d2dd', '788ef2f021a73cba2794b616078a8500', - 'e6e7e8e9ebecedeef0f1f2f3f5f6f7f8fafbfcfdfe010002', - 'ecb-tbl-192: I=80'), - ('76777475f1f2f3f4f8f9e6e777707172', '5d1ef20dced6bcbc12131ac7c54788aa', - '04050607090a0b0c0e0f10111314151618191a1b1d1e1f20', - 'ecb-tbl-192: I=81'), - ('a4a5a2a34f404142b4b5b6b727242522', 'b3c8cf961faf9ea05fdde6d1e4d8f663', - '222324252728292a2c2d2e2f31323334363738393b3c3d3e', - 'ecb-tbl-192: I=82'), - ('94959697e1e2e3ec16171011839c9d9e', '143075c70605861c7fac6526199e459f', - '40414243454647484a4b4c4d4f50515254555657595a5b5c', - 'ecb-tbl-192: I=83'), - ('03023d3c06010003dedfdcddfffcfde2', 'a5ae12eade9a87268d898bfc8fc0252a', - '5e5f60616364656668696a6b6d6e6f70727374757778797a', - 'ecb-tbl-192: I=84'), - ('10111213f1f2f3f4cecfc0c1dbdcddde', '0924f7cf2e877a4819f5244a360dcea9', - '7c7d7e7f81828384868788898b8c8d8e9091929395969798', - 'ecb-tbl-192: I=85'), - ('67666160724d4c4f1d1c1f1e73707176', '3d9e9635afcc3e291cc7ab3f27d1c99a', - '9a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', - 'ecb-tbl-192: I=86'), - ('e6e7e4e5a8abaad584858283909f9e9d', '9d80feebf87510e2b8fb98bb54fd788c', - 'b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4', - 'ecb-tbl-192: I=87'), - ('71707f7e565150537d7c7f7e6162636c', '5f9d1a082a1a37985f174002eca01309', - 'd6d7d8d9dbdcdddee0e1e2e3e5e6e7e8eaebecedeff0f1f2', - 'ecb-tbl-192: I=88'), - ('64656667212223245555aaaa03040506', 'a390ebb1d1403930184a44b4876646e4', - 'f4f5f6f7f9fafbfcfefe01010304050608090a0b0d0e0f10', - 'ecb-tbl-192: I=89'), - ('9e9f9899aba4a5a6cfcecdcc2b28292e', '700fe918981c3195bb6c4bcb46b74e29', - '121314151718191a1c1d1e1f21222324262728292b2c2d2e', - 'ecb-tbl-192: I=90'), - ('c7c6c5c4d1d2d3dc626364653a454447', '907984406f7bf2d17fb1eb15b673d747', - '30313233353637383a3b3c3d3f40414244454647494a4b4c', - 'ecb-tbl-192: I=91'), - ('f6f7e8e9e0e7e6e51d1c1f1e5b585966', 'c32a956dcfc875c2ac7c7cc8b8cc26e1', - '4e4f50515354555658595a5b5d5e5f60626364656768696a', - 'ecb-tbl-192: I=92'), - ('bcbdbebf5d5e5f5868696667f4f3f2f1', '02646e2ebfa9b820cf8424e9b9b6eb51', - '6c6d6e6f71727374767778797b7c7d7e8081828385868788', - 'ecb-tbl-192: I=93'), - ('40414647b0afaead9b9a99989b98999e', '621fda3a5bbd54c6d3c685816bd4ead8', - '8a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6', - 'ecb-tbl-192: I=94'), - ('69686b6a0201001f0f0e0908b4bbbab9', 'd4e216040426dfaf18b152469bc5ac2f', - 'a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4', - 'ecb-tbl-192: I=95'), - ('c7c6c9c8d8dfdedd5a5b5859bebdbcb3', '9d0635b9d33b6cdbd71f5d246ea17cc8', - 'c6c7c8c9cbcccdced0d1d2d3d5d6d7d8dadbdcdddfe0e1e2', - 'ecb-tbl-192: I=96'), - ('dedfdcdd787b7a7dfffee1e0b2b5b4b7', '10abad1bd9bae5448808765583a2cc1a', - 'e4e5e6e7e9eaebeceeeff0f1f3f4f5f6f8f9fafbfdfefe00', - 'ecb-tbl-192: I=97'), - ('4d4c4b4a606f6e6dd0d1d2d3fbf8f9fe', '6891889e16544e355ff65a793c39c9a8', - '020304050708090a0c0d0e0f11121314161718191b1c1d1e', - 'ecb-tbl-192: I=98'), - ('b7b6b5b4d7d4d5dae5e4e3e2e1fefffc', 'cc735582e68072c163cd9ddf46b91279', - '20212223252627282a2b2c2d2f30313234353637393a3b3c', - 'ecb-tbl-192: I=99'), - ('cecfb0b1f7f0f1f2aeafacad3e3d3c23', 'c5c68b9aeeb7f878df578efa562f9574', - '3e3f40414344454648494a4b4d4e4f50525354555758595a', - 'ecb-tbl-192: I=100'), - ('cacbc8c9cdcecfc812131c1d494e4f4c', '5f4764395a667a47d73452955d0d2ce8', - '5c5d5e5f61626364666768696b6c6d6e7071727375767778', - 'ecb-tbl-192: I=101'), - ('9d9c9b9ad22d2c2fb1b0b3b20c0f0e09', '701448331f66106cefddf1eb8267c357', - '7a7b7c7d7f80818284858687898a8b8c8e8f909193949596', - 'ecb-tbl-192: I=102'), - ('7a7b787964676659959493924f404142', 'cb3ee56d2e14b4e1941666f13379d657', - '98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4', - 'ecb-tbl-192: I=103'), - ('aaaba4a5cec9c8cb1f1e1d1caba8a9a6', '9fe16efd18ab6e1981191851fedb0764', - 'b6b7b8b9bbbcbdbec0c1c2c3c5c6c7c8cacbcccdcfd0d1d2', - 'ecb-tbl-192: I=104'), - ('93929190282b2a2dc4c5fafb92959497', '3dc9ba24e1b223589b147adceb4c8e48', - 'd4d5d6d7d9dadbdcdedfe0e1e3e4e5e6e8e9eaebedeeeff0', - 'ecb-tbl-192: I=105'), - ('efeee9e8ded1d0d339383b3a888b8a8d', '1c333032682e7d4de5e5afc05c3e483c', - 'f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e', - 'ecb-tbl-192: I=106'), - ('7f7e7d7ca2a1a0af78797e7f112e2f2c', 'd593cc99a95afef7e92038e05a59d00a', - '10111213151617181a1b1c1d1f20212224252627292a2b2c', - 'ecb-tbl-192: I=107'), - ('84859a9b2b2c2d2e868784852625245b', '51e7f96f53b4353923452c222134e1ec', - '2e2f30313334353638393a3b3d3e3f40424344454748494a', - 'ecb-tbl-192: I=108'), - ('b0b1b2b3070405026869666710171615', '4075b357a1a2b473400c3b25f32f81a4', - '4c4d4e4f51525354565758595b5c5d5e6061626365666768', - 'ecb-tbl-192: I=109'), - ('acadaaabbda2a3a00d0c0f0e595a5b5c', '302e341a3ebcd74f0d55f61714570284', - '6a6b6c6d6f70717274757677797a7b7c7e7f808183848586', - 'ecb-tbl-192: I=110'), - ('121310115655544b5253545569666764', '57abdd8231280da01c5042b78cf76522', - '88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4', - 'ecb-tbl-192: I=111'), - ('dedfd0d166616063eaebe8e94142434c', '17f9ea7eea17ac1adf0e190fef799e92', - 'a6a7a8a9abacadaeb0b1b2b3b5b6b7b8babbbcbdbfc0c1c2', - 'ecb-tbl-192: I=112'), - ('dbdad9d81417161166677879e0e7e6e5', '2e1bdd563dd87ee5c338dd6d098d0a7a', - 'c4c5c6c7c9cacbcccecfd0d1d3d4d5d6d8d9dadbdddedfe0', - 'ecb-tbl-192: I=113'), - ('6a6b6c6de0efeeed2b2a2928c0c3c2c5', 'eb869996e6f8bfb2bfdd9e0c4504dbb2', - 'e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', - 'ecb-tbl-192: I=114'), - ('b1b0b3b21714151a1a1b1c1d5649484b', 'c2e01549e9decf317468b3e018c61ba8', - '00010203050607080a0b0c0d0f10111214151617191a1b1c', - 'ecb-tbl-192: I=115'), - ('39380706a3a4a5a6c4c5c6c77271706f', '8da875d033c01dd463b244a1770f4a22', - '1e1f20212324252628292a2b2d2e2f30323334353738393a', - 'ecb-tbl-192: I=116'), - ('5c5d5e5f1013121539383736e2e5e4e7', '8ba0dcf3a186844f026d022f8839d696', - '3c3d3e3f41424344464748494b4c4d4e5051525355565758', - 'ecb-tbl-192: I=117'), - ('43424544ead5d4d72e2f2c2d64676661', 'e9691ff9a6cc6970e51670a0fd5b88c1', - '5a5b5c5d5f60616264656667696a6b6c6e6f707173747576', - 'ecb-tbl-192: I=118'), - ('55545756989b9a65f8f9feff18171615', 'f2baec06faeed30f88ee63ba081a6e5b', - '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394', - 'ecb-tbl-192: I=119'), - ('05040b0a525554573c3d3e3f4a494847', '9c39d4c459ae5753394d6094adc21e78', - '969798999b9c9d9ea0a1a2a3a5a6a7a8aaabacadafb0b1b2', - 'ecb-tbl-192: I=120'), - ('14151617595a5b5c8584fbfa8e89888b', '6345b532a11904502ea43ba99c6bd2b2', - 'b4b5b6b7b9babbbcbebfc0c1c3c4c5c6c8c9cacbcdcecfd0', - 'ecb-tbl-192: I=121'), - ('7c7d7a7bfdf2f3f029282b2a51525354', '5ffae3061a95172e4070cedce1e428c8', - 'd2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-192: I=122'), - ('38393a3b1e1d1c1341404746c23d3c3e', '0a4566be4cdf9adce5dec865b5ab34cd', - 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c', - 'ecb-tbl-192: I=123'), - ('8d8c939240474645818083827c7f7e41', 'ca17fcce79b7404f2559b22928f126fb', - '0e0f10111314151618191a1b1d1e1f20222324252728292a', - 'ecb-tbl-192: I=124'), - ('3b3a39381a19181f32333c3d45424340', '97ca39b849ed73a6470a97c821d82f58', - '2c2d2e2f31323334363738393b3c3d3e4041424345464748', - 'ecb-tbl-192: I=125'), - ('f0f1f6f738272625828380817f7c7d7a', '8198cb06bc684c6d3e9b7989428dcf7a', - '4a4b4c4d4f50515254555657595a5b5c5e5f606163646566', - 'ecb-tbl-192: I=126'), - ('89888b8a0407061966676061141b1a19', 'f53c464c705ee0f28d9a4c59374928bd', - '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384', - 'ecb-tbl-192: I=127'), - ('d3d2dddcaaadacaf9c9d9e9fe8ebeae5', '9adb3d4cca559bb98c3e2ed73dbf1154', - '868788898b8c8d8e90919293959697989a9b9c9d9fa0a1a2', - 'ecb-tbl-192: I=128'), - - # ecb_tbl.txt, KEYSIZE=256 - ('834eadfccac7e1b30664b1aba44815ab', '1946dabf6a03a2a2c3d0b05080aed6fc', - '00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526', - 'ecb-tbl-256: I=1'), - ('d9dc4dba3021b05d67c0518f72b62bf1', '5ed301d747d3cc715445ebdec62f2fb4', - '28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-256: I=2'), - ('a291d86301a4a739f7392173aa3c604c', '6585c8f43d13a6beab6419fc5935b9d0', - '50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576', - 'ecb-tbl-256: I=3'), - ('4264b2696498de4df79788a9f83e9390', '2a5b56a596680fcc0e05f5e0f151ecae', - '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-256: I=4'), - ('ee9932b3721804d5a83ef5949245b6f6', 'f5d6ff414fd2c6181494d20c37f2b8c4', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', - 'ecb-tbl-256: I=5'), - ('e6248f55c5fdcbca9cbbb01c88a2ea77', '85399c01f59fffb5204f19f8482f00b8', - 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-256: I=6'), - ('b8358e41b9dff65fd461d55a99266247', '92097b4c88a041ddf98144bc8d22e8e7', - 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516', - 'ecb-tbl-256: I=7'), - ('f0e2d72260af58e21e015ab3a4c0d906', '89bd5b73b356ab412aef9f76cea2d65c', - '18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e', - 'ecb-tbl-256: I=8'), - ('475b8b823ce8893db3c44a9f2a379ff7', '2536969093c55ff9454692f2fac2f530', - '40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566', - 'ecb-tbl-256: I=9'), - ('688f5281945812862f5f3076cf80412f', '07fc76a872843f3f6e0081ee9396d637', - '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e', - 'ecb-tbl-256: I=10'), - ('08d1d2bc750af553365d35e75afaceaa', 'e38ba8ec2aa741358dcc93e8f141c491', - '90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', - 'ecb-tbl-256: I=11'), - ('8707121f47cc3efceca5f9a8474950a1', 'd028ee23e4a89075d0b03e868d7d3a42', - 'b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde', - 'ecb-tbl-256: I=12'), - ('e51aa0b135dba566939c3b6359a980c5', '8cd9423dfc459e547155c5d1d522e540', - 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506', - 'ecb-tbl-256: I=13'), - ('069a007fc76a459f98baf917fedf9521', '080e9517eb1677719acf728086040ae3', - '08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e', - 'ecb-tbl-256: I=14'), - ('726165c1723fbcf6c026d7d00b091027', '7c1700211a3991fc0ecded0ab3e576b0', - '30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556', - 'ecb-tbl-256: I=15'), - ('d7c544de91d55cfcde1f84ca382200ce', 'dabcbcc855839251db51e224fbe87435', - '58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e', - 'ecb-tbl-256: I=16'), - ('fed3c9a161b9b5b2bd611b41dc9da357', '68d56fad0406947a4dd27a7448c10f1d', - '80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6', - 'ecb-tbl-256: I=17'), - ('4f634cdc6551043409f30b635832cf82', 'da9a11479844d1ffee24bbf3719a9925', - 'a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce', - 'ecb-tbl-256: I=18'), - ('109ce98db0dfb36734d9f3394711b4e6', '5e4ba572f8d23e738da9b05ba24b8d81', - 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', - 'ecb-tbl-256: I=19'), - ('4ea6dfaba2d8a02ffdffa89835987242', 'a115a2065d667e3f0b883837a6e903f8', - '70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596', - 'ecb-tbl-256: I=20'), - ('5ae094f54af58e6e3cdbf976dac6d9ef', '3e9e90dc33eac2437d86ad30b137e66e', - '98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe', - 'ecb-tbl-256: I=21'), - ('764d8e8e0f29926dbe5122e66354fdbe', '01ce82d8fbcdae824cb3c48e495c3692', - 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', - 'ecb-tbl-256: I=22'), - ('3f0418f888cdf29a982bf6b75410d6a9', '0c9cff163ce936faaf083cfd3dea3117', - 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e', - 'ecb-tbl-256: I=23'), - ('e4a3e7cb12cdd56aa4a75197a9530220', '5131ba9bd48f2bba85560680df504b52', - '10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536', - 'ecb-tbl-256: I=24'), - ('211677684aac1ec1a160f44c4ebf3f26', '9dc503bbf09823aec8a977a5ad26ccb2', - '38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e', - 'ecb-tbl-256: I=25'), - ('d21e439ff749ac8f18d6d4b105e03895', '9a6db0c0862e506a9e397225884041d7', - '60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586', - 'ecb-tbl-256: I=26'), - ('d9f6ff44646c4725bd4c0103ff5552a7', '430bf9570804185e1ab6365fc6a6860c', - '88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae', - 'ecb-tbl-256: I=27'), - ('0b1256c2a00b976250cfc5b0c37ed382', '3525ebc02f4886e6a5a3762813e8ce8a', - 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', - 'ecb-tbl-256: I=28'), - ('b056447ffc6dc4523a36cc2e972a3a79', '07fa265c763779cce224c7bad671027b', - 'd8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', - 'ecb-tbl-256: I=29'), - ('5e25ca78f0de55802524d38da3fe4456', 'e8b72b4e8be243438c9fff1f0e205872', - '00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526', - 'ecb-tbl-256: I=30'), - ('a5bcf4728fa5eaad8567c0dc24675f83', '109d4f999a0e11ace1f05e6b22cbcb50', - '28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-256: I=31'), - ('814e59f97ed84646b78b2ca022e9ca43', '45a5e8d4c3ed58403ff08d68a0cc4029', - '50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576', - 'ecb-tbl-256: I=32'), - ('15478beec58f4775c7a7f5d4395514d7', '196865964db3d417b6bd4d586bcb7634', - '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-256: I=33'), - ('253548ffca461c67c8cbc78cd59f4756', '60436ad45ac7d30d99195f815d98d2ae', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', - 'ecb-tbl-256: I=34'), - ('fd7ad8d73b9b0f8cc41600640f503d65', 'bb07a23f0b61014b197620c185e2cd75', - 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-256: I=35'), - ('06199de52c6cbf8af954cd65830bcd56', '5bc0b2850129c854423aff0751fe343b', - 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516', - 'ecb-tbl-256: I=36'), - ('f17c4ffe48e44c61bd891e257e725794', '7541a78f96738e6417d2a24bd2beca40', - '18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e', - 'ecb-tbl-256: I=37'), - ('9a5b4a402a3e8a59be6bf5cd8154f029', 'b0a303054412882e464591f1546c5b9e', - '40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566', - 'ecb-tbl-256: I=38'), - ('79bd40b91a7e07dc939d441782ae6b17', '778c06d8a355eeee214fcea14b4e0eef', - '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e', - 'ecb-tbl-256: I=39'), - ('d8ceaaf8976e5fbe1012d8c84f323799', '09614206d15cbace63227d06db6beebb', - '90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', - 'ecb-tbl-256: I=40'), - ('3316e2751e2e388b083da23dd6ac3fbe', '41b97fb20e427a9fdbbb358d9262255d', - 'b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde', - 'ecb-tbl-256: I=41'), - ('8b7cfbe37de7dca793521819242c5816', 'c1940f703d845f957652c2d64abd7adf', - 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506', - 'ecb-tbl-256: I=42'), - ('f23f033c0eebf8ec55752662fd58ce68', 'd2d44fcdae5332343366db297efcf21b', - '08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e', - 'ecb-tbl-256: I=43'), - ('59eb34f6c8bdbacc5fc6ad73a59a1301', 'ea8196b79dbe167b6aa9896e287eed2b', - '30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556', - 'ecb-tbl-256: I=44'), - ('dcde8b6bd5cf7cc22d9505e3ce81261a', 'd6b0b0c4ba6c7dbe5ed467a1e3f06c2d', - '58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e', - 'ecb-tbl-256: I=45'), - ('e33cf7e524fed781e7042ff9f4b35dc7', 'ec51eb295250c22c2fb01816fb72bcae', - '80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6', - 'ecb-tbl-256: I=46'), - ('27963c8facdf73062867d164df6d064c', 'aded6630a07ce9c7408a155d3bd0d36f', - 'a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce', - 'ecb-tbl-256: I=47'), - ('77b1ce386b551b995f2f2a1da994eef8', '697c9245b9937f32f5d1c82319f0363a', - 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', - 'ecb-tbl-256: I=48'), - ('f083388b013679efcf0bb9b15d52ae5c', 'aad5ad50c6262aaec30541a1b7b5b19c', - 'f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314161718191b1c1d1e', - 'ecb-tbl-256: I=49'), - ('c5009e0dab55db0abdb636f2600290c8', '7d34b893855341ec625bd6875ac18c0d', - '20212223252627282a2b2c2d2f30313234353637393a3b3c3e3f404143444546', - 'ecb-tbl-256: I=50'), - ('7804881e26cd532d8514d3683f00f1b9', '7ef05105440f83862f5d780e88f02b41', - '48494a4b4d4e4f50525354555758595a5c5d5e5f61626364666768696b6c6d6e', - 'ecb-tbl-256: I=51'), - ('46cddcd73d1eb53e675ca012870a92a3', 'c377c06403382061af2c9c93a8e70df6', - '70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596', - 'ecb-tbl-256: I=52'), - ('a9fb44062bb07fe130a8e8299eacb1ab', '1dbdb3ffdc052dacc83318853abc6de5', - '98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe', - 'ecb-tbl-256: I=53'), - ('2b6ff8d7a5cc3a28a22d5a6f221af26b', '69a6eab00432517d0bf483c91c0963c7', - 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', - 'ecb-tbl-256: I=54'), - ('1a9527c29b8add4b0e3e656dbb2af8b4', '0797f41dc217c80446e1d514bd6ab197', - 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e', - 'ecb-tbl-256: I=55'), - ('7f99cf2c75244df015eb4b0c1050aeae', '9dfd76575902a637c01343c58e011a03', - '10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536', - 'ecb-tbl-256: I=56'), - ('e84ff85b0d9454071909c1381646c4ed', 'acf4328ae78f34b9fa9b459747cc2658', - '38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e', - 'ecb-tbl-256: I=57'), - ('89afd40f99521280d5399b12404f6db4', 'b0479aea12bac4fe2384cf98995150c6', - '60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586', - 'ecb-tbl-256: I=58'), - ('a09ef32dbc5119a35ab7fa38656f0329', '9dd52789efe3ffb99f33b3da5030109a', - '88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae', - 'ecb-tbl-256: I=59'), - ('61773457f068c376c7829b93e696e716', 'abbb755e4621ef8f1214c19f649fb9fd', - 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', - 'ecb-tbl-256: I=60'), - ('a34f0cae726cce41dd498747d891b967', 'da27fb8174357bce2bed0e7354f380f9', - 'd8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', - 'ecb-tbl-256: I=61'), - ('856f59496c7388ee2d2b1a27b7697847', 'c59a0663f0993838f6e5856593bdc5ef', - '00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526', - 'ecb-tbl-256: I=62'), - ('cb090c593ef7720bd95908fb93b49df4', 'ed60b264b5213e831607a99c0ce5e57e', - '28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-256: I=63'), - ('a0ac75cd2f1923d460fc4d457ad95baf', 'e50548746846f3eb77b8c520640884ed', - '50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576', - 'ecb-tbl-256: I=64'), - ('2a2b282974777689e8e9eeef525d5c5f', '28282cc7d21d6a2923641e52d188ef0c', - '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-256: I=65'), - ('909192939390919e0f0e09089788898a', '0dfa5b02abb18e5a815305216d6d4f8e', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', - 'ecb-tbl-256: I=66'), - ('777675748d8e8f907170777649464744', '7359635c0eecefe31d673395fb46fb99', - 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-256: I=67'), - ('717073720605040b2d2c2b2a05fafbf9', '73c679f7d5aef2745c9737bb4c47fb36', - 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516', - 'ecb-tbl-256: I=68'), - ('64656667fefdfcc31b1a1d1ca5aaaba8', 'b192bd472a4d2eafb786e97458967626', - '18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e', - 'ecb-tbl-256: I=69'), - ('dbdad9d86a696867b5b4b3b2c8d7d6d5', '0ec327f6c8a2b147598ca3fde61dc6a4', - '40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566', - 'ecb-tbl-256: I=70'), - ('5c5d5e5fe3e0e1fe31303736333c3d3e', 'fc418eb3c41b859b38d4b6f646629729', - '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e', - 'ecb-tbl-256: I=71'), - ('545556574b48494673727574546b6a69', '30249e5ac282b1c981ea64b609f3a154', - '90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', - 'ecb-tbl-256: I=72'), - ('ecedeeefc6c5c4bb56575051f5fafbf8', '5e6e08646d12150776bb43c2d78a9703', - 'b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde', - 'ecb-tbl-256: I=73'), - ('464744452724252ac9c8cfced2cdcccf', 'faeb3d5de652cd3447dceb343f30394a', - 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506', - 'ecb-tbl-256: I=74'), - ('e6e7e4e54142435c878681801c131211', 'a8e88706823f6993ef80d05c1c7b2cf0', - '08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e', - 'ecb-tbl-256: I=75'), - ('72737071cfcccdc2f9f8fffe710e0f0c', '8ced86677e6e00a1a1b15968f2d3cce6', - '30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556', - 'ecb-tbl-256: I=76'), - ('505152537370714ec3c2c5c4010e0f0c', '9fc7c23858be03bdebb84e90db6786a9', - '58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e', - 'ecb-tbl-256: I=77'), - ('a8a9aaab5c5f5e51aeafa8a93d222320', 'b4fbd65b33f70d8cf7f1111ac4649c36', - '80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6', - 'ecb-tbl-256: I=78'), - ('dedfdcddf6f5f4eb10111617fef1f0f3', 'c5c32d5ed03c4b53cc8c1bd0ef0dbbf6', - 'a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce', - 'ecb-tbl-256: I=79'), - ('bdbcbfbe5e5d5c530b0a0d0cfac5c4c7', 'd1a7f03b773e5c212464b63709c6a891', - 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', - 'ecb-tbl-256: I=80'), - ('8a8b8889050606f8f4f5f2f3636c6d6e', '6b7161d8745947ac6950438ea138d028', - 'f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314161718191b1c1d1e', - 'ecb-tbl-256: I=81'), - ('a6a7a4a54d4e4f40b2b3b4b539262724', 'fd47a9f7e366ee7a09bc508b00460661', - '20212223252627282a2b2c2d2f30313234353637393a3b3c3e3f404143444546', - 'ecb-tbl-256: I=82'), - ('9c9d9e9fe9eaebf40e0f08099b949596', '00d40b003dc3a0d9310b659b98c7e416', - '48494a4b4d4e4f50525354555758595a5c5d5e5f61626364666768696b6c6d6e', - 'ecb-tbl-256: I=83'), - ('2d2c2f2e1013121dcccdcacbed121310', 'eea4c79dcc8e2bda691f20ac48be0717', - '70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596', - 'ecb-tbl-256: I=84'), - ('f4f5f6f7edeeefd0eaebecedf7f8f9fa', 'e78f43b11c204403e5751f89d05a2509', - '98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe', - 'ecb-tbl-256: I=85'), - ('3d3c3f3e282b2a2573727574150a0b08', 'd0f0e3d1f1244bb979931e38dd1786ef', - 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', - 'ecb-tbl-256: I=86'), - ('b6b7b4b5f8fbfae5b4b5b2b3a0afaead', '042e639dc4e1e4dde7b75b749ea6f765', - 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e', - 'ecb-tbl-256: I=87'), - ('b7b6b5b4989b9a95878681809ba4a5a6', 'bc032fdd0efe29503a980a7d07ab46a8', - '10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536', - 'ecb-tbl-256: I=88'), - ('a8a9aaabe5e6e798e9e8efee4748494a', '0c93ac949c0da6446effb86183b6c910', - '38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e', - 'ecb-tbl-256: I=89'), - ('ecedeeefd9dadbd4b9b8bfbe657a7b78', 'e0d343e14da75c917b4a5cec4810d7c2', - '60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586', - 'ecb-tbl-256: I=90'), - ('7f7e7d7c696a6b74cacbcccd929d9c9f', '0eafb821748408279b937b626792e619', - '88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae', - 'ecb-tbl-256: I=91'), - ('08090a0b0605040bfffef9f8b9c6c7c4', 'fa1ac6e02d23b106a1fef18b274a553f', - 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', - 'ecb-tbl-256: I=92'), - ('08090a0bf1f2f3ccfcfdfafb68676665', '0dadfe019cd12368075507df33c1a1e9', - 'd8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', - 'ecb-tbl-256: I=93'), - ('cacbc8c93a393837050403020d121310', '3a0879b414465d9ffbaf86b33a63a1b9', - '00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526', - 'ecb-tbl-256: I=94'), - ('e9e8ebea8281809f8f8e8988343b3a39', '62199fadc76d0be1805d3ba0b7d914bf', - '28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-256: I=95'), - ('515053524645444bd0d1d6d7340b0a09', '1b06d6c5d333e742730130cf78e719b4', - '50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576', - 'ecb-tbl-256: I=96'), - ('42434041ecefee1193929594c6c9c8cb', 'f1f848824c32e9dcdcbf21580f069329', - '78797a7b7d7e7f80828384858788898a8c8d8e8f91929394969798999b9c9d9e', - 'ecb-tbl-256: I=97'), - ('efeeedecc2c1c0cf76777071455a5b58', '1a09050cbd684f784d8e965e0782f28a', - 'a0a1a2a3a5a6a7a8aaabacadafb0b1b2b4b5b6b7b9babbbcbebfc0c1c3c4c5c6', - 'ecb-tbl-256: I=98'), - ('5f5e5d5c3f3c3d221d1c1b1a19161714', '79c2969e7ded2ba7d088f3f320692360', - 'c8c9cacbcdcecfd0d2d3d4d5d7d8d9dadcdddedfe1e2e3e4e6e7e8e9ebecedee', - 'ecb-tbl-256: I=99'), - ('000102034142434c1c1d1a1b8d727371', '091a658a2f7444c16accb669450c7b63', - 'f0f1f2f3f5f6f7f8fafbfcfdfe01000204050607090a0b0c0e0f101113141516', - 'ecb-tbl-256: I=100'), - ('8e8f8c8db1b2b38c56575051050a0b08', '97c1e3a72cca65fa977d5ed0e8a7bbfc', - '18191a1b1d1e1f20222324252728292a2c2d2e2f31323334363738393b3c3d3e', - 'ecb-tbl-256: I=101'), - ('a7a6a5a4e8ebeae57f7e7978cad5d4d7', '70c430c6db9a17828937305a2df91a2a', - '40414243454647484a4b4c4d4f50515254555657595a5b5c5e5f606163646566', - 'ecb-tbl-256: I=102'), - ('8a8b888994979689454443429f909192', '629553457fbe2479098571c7c903fde8', - '68696a6b6d6e6f70727374757778797a7c7d7e7f81828384868788898b8c8d8e', - 'ecb-tbl-256: I=103'), - ('8c8d8e8fe0e3e2ed45444342f1cecfcc', 'a25b25a61f612669e7d91265c7d476ba', - '90919293959697989a9b9c9d9fa0a1a2a4a5a6a7a9aaabacaeafb0b1b3b4b5b6', - 'ecb-tbl-256: I=104'), - ('fffefdfc4c4f4e31d8d9dedfb6b9b8bb', 'eb7e4e49b8ae0f024570dda293254fed', - 'b8b9babbbdbebfc0c2c3c4c5c7c8c9cacccdcecfd1d2d3d4d6d7d8d9dbdcddde', - 'ecb-tbl-256: I=105'), - ('fdfcfffecccfcec12f2e29286679787b', '38fe15d61cca84516e924adce5014f67', - 'e0e1e2e3e5e6e7e8eaebecedeff0f1f2f4f5f6f7f9fafbfcfefe010103040506', - 'ecb-tbl-256: I=106'), - ('67666564bab9b8a77071767719161714', '3ad208492249108c9f3ebeb167ad0583', - '08090a0b0d0e0f10121314151718191a1c1d1e1f21222324262728292b2c2d2e', - 'ecb-tbl-256: I=107'), - ('9a9b98992d2e2f2084858283245b5a59', '299ba9f9bf5ab05c3580fc26edd1ed12', - '30313233353637383a3b3c3d3f40414244454647494a4b4c4e4f505153545556', - 'ecb-tbl-256: I=108'), - ('a4a5a6a70b0809365c5d5a5b2c232221', '19dc705b857a60fb07717b2ea5717781', - '58595a5b5d5e5f60626364656768696a6c6d6e6f71727374767778797b7c7d7e', - 'ecb-tbl-256: I=109'), - ('464744455754555af3f2f5f4afb0b1b2', 'ffc8aeb885b5efcad06b6dbebf92e76b', - '80818283858687888a8b8c8d8f90919294959697999a9b9c9e9fa0a1a3a4a5a6', - 'ecb-tbl-256: I=110'), - ('323330317675746b7273747549464744', 'f58900c5e0b385253ff2546250a0142b', - 'a8a9aaabadaeafb0b2b3b4b5b7b8b9babcbdbebfc1c2c3c4c6c7c8c9cbcccdce', - 'ecb-tbl-256: I=111'), - ('a8a9aaab181b1a15808186872b141516', '2ee67b56280bc462429cee6e3370cbc1', - 'd0d1d2d3d5d6d7d8dadbdcdddfe0e1e2e4e5e6e7e9eaebeceeeff0f1f3f4f5f6', - 'ecb-tbl-256: I=112'), - ('e7e6e5e4202323ddaaabacad343b3a39', '20db650a9c8e9a84ab4d25f7edc8f03f', - 'f8f9fafbfdfefe00020304050708090a0c0d0e0f11121314161718191b1c1d1e', - 'ecb-tbl-256: I=113'), - ('a8a9aaab2221202fedecebea1e010003', '3c36da169525cf818843805f25b78ae5', - '20212223252627282a2b2c2d2f30313234353637393a3b3c3e3f404143444546', - 'ecb-tbl-256: I=114'), - ('f9f8fbfa5f5c5d42424344450e010003', '9a781d960db9e45e37779042fea51922', - '48494a4b4d4e4f50525354555758595a5c5d5e5f61626364666768696b6c6d6e', - 'ecb-tbl-256: I=115'), - ('57565554f5f6f7f89697909120dfdedd', '6560395ec269c672a3c288226efdba77', - '70717273757677787a7b7c7d7f80818284858687898a8b8c8e8f909193949596', - 'ecb-tbl-256: I=116'), - ('f8f9fafbcccfcef1dddcdbda0e010003', '8c772b7a189ac544453d5916ebb27b9a', - '98999a9b9d9e9fa0a2a3a4a5a7a8a9aaacadaeafb1b2b3b4b6b7b8b9bbbcbdbe', - 'ecb-tbl-256: I=117'), - ('d9d8dbda7073727d80818687c2dddcdf', '77ca5468cc48e843d05f78eed9d6578f', - 'c0c1c2c3c5c6c7c8cacbcccdcfd0d1d2d4d5d6d7d9dadbdcdedfe0e1e3e4e5e6', - 'ecb-tbl-256: I=118'), - ('c5c4c7c6080b0a1588898e8f68676665', '72cdcc71dc82c60d4429c9e2d8195baa', - 'e8e9eaebedeeeff0f2f3f4f5f7f8f9fafcfdfeff01020304060708090b0c0d0e', - 'ecb-tbl-256: I=119'), - ('83828180dcdfded186878081f0cfcecd', '8080d68ce60e94b40b5b8b69eeb35afa', - '10111213151617181a1b1c1d1f20212224252627292a2b2c2e2f303133343536', - 'ecb-tbl-256: I=120'), - ('98999a9bdddedfa079787f7e0a050407', '44222d3cde299c04369d58ac0eba1e8e', - '38393a3b3d3e3f40424344454748494a4c4d4e4f51525354565758595b5c5d5e', - 'ecb-tbl-256: I=121'), - ('cecfcccd4f4c4d429f9e9998dfc0c1c2', '9b8721b0a8dfc691c5bc5885dbfcb27a', - '60616263656667686a6b6c6d6f70717274757677797a7b7c7e7f808183848586', - 'ecb-tbl-256: I=122'), - ('404142436665647b29282f2eaba4a5a6', '0dc015ce9a3a3414b5e62ec643384183', - '88898a8b8d8e8f90929394959798999a9c9d9e9fa1a2a3a4a6a7a8a9abacadae', - 'ecb-tbl-256: I=123'), - ('33323130e6e5e4eb23222524dea1a0a3', '705715448a8da412025ce38345c2a148', - 'b0b1b2b3b5b6b7b8babbbcbdbfc0c1c2c4c5c6c7c9cacbcccecfd0d1d3d4d5d6', - 'ecb-tbl-256: I=124'), - ('cfcecdccf6f5f4cbe6e7e0e199969794', 'c32b5b0b6fbae165266c569f4b6ecf0b', - 'd8d9dadbdddedfe0e2e3e4e5e7e8e9eaecedeeeff1f2f3f4f6f7f8f9fbfcfdfe', - 'ecb-tbl-256: I=125'), - ('babbb8b97271707fdcdddadb29363734', '4dca6c75192a01ddca9476af2a521e87', - '00010203050607080a0b0c0d0f10111214151617191a1b1c1e1f202123242526', - 'ecb-tbl-256: I=126'), - ('c9c8cbca4447465926272021545b5a59', '058691e627ecbc36ac07b6db423bd698', - '28292a2b2d2e2f30323334353738393a3c3d3e3f41424344464748494b4c4d4e', - 'ecb-tbl-256: I=127'), - ('050407067477767956575051221d1c1f', '7444527095838fe080fc2bcdd30847eb', - '50515253555657585a5b5c5d5f60616264656667696a6b6c6e6f707173747576', - 'ecb-tbl-256: I=128'), - - # FIPS PUB 800-38A test vectors, 2001 edition. Annex F. - - ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', - '3ad77bb40d7a3660a89ecaf32466ef97'+'f5d3d58503b9699de785895a96fdbaaf'+ - '43b1cd7f598ece23881b00e3ed030688'+'7b0c785e27e8ad3f8223207104725dd4', - '2b7e151628aed2a6abf7158809cf4f3c', - 'NIST 800-38A, F.1.1, ECB and AES-128'), - - ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', - 'bd334f1d6e45f25ff712a214571fa5cc'+'974104846d0ad3ad7734ecb3ecee4eef'+ - 'ef7afd2270e2e60adce0ba2face6444e'+'9a4b41ba738d6c72fb16691603c18e0e', - '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b', - 'NIST 800-38A, F.1.3, ECB and AES-192'), - - ('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710', - 'f3eed1bdb5d2a03c064b5a7e3db181f8'+'591ccb10d410ed26dc5ba74a31362870'+ - 'b6ed21b99ca6f4f9f153e7b1beafed1d'+'23304b7a39f9f3ff067d8d8f9e24ecc7', - '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4', - 'NIST 800-38A, F.1.3, ECB and AES-256'), - -] - -test_data_8_lanes = [] -for td in test_data: - test_data_8_lanes.append((td[0] * 8, td[1] * 8, td[2], td[3])) -test_data += test_data_8_lanes - -class TestMultipleBlocks(unittest.TestCase): - - def __init__(self, use_aesni): - unittest.TestCase.__init__(self) - self.use_aesni = use_aesni - - def runTest(self): - # Encrypt data which is 8*2+4 bytes long, so as to trigger (for the - # AESNI variant) both the path that parallelizes 8 lanes and the one - # that processes data serially - - tvs = [ - (b'a' * 16, 'c0b27011eb15bf144d2fc9fae80ea16d4c231cb230416c5fac02e6835ad9d7d0'), - (b'a' * 24, 'df8435ce361a78c535b41dcb57da952abbf9ee5954dc6fbcd75fd00fa626915d'), - (b'a' * 32, '211402de6c80db1f92ba255881178e1f70783b8cfd3b37808205e48b80486cd8') - ] - - for key, expected in tvs: - - cipher = AES.new(key, AES.MODE_ECB, use_aesni=self.use_aesni) - h = SHA256.new() - - pt = b"".join([ tobytes('{0:016x}'.format(x)) for x in range(20) ]) - ct = cipher.encrypt(pt) - self.assertEqual(SHA256.new(ct).hexdigest(), expected) - - -class TestIncompleteBlocks(unittest.TestCase): - - def __init__(self, use_aesni): - unittest.TestCase.__init__(self) - self.use_aesni = use_aesni - - def runTest(self): - # Encrypt data with length not multiple of 16 bytes - - cipher = AES.new(b'4'*16, AES.MODE_ECB, use_aesni=self.use_aesni) - - for msg_len in range(1, 16): - self.assertRaises(ValueError, cipher.encrypt, b'1' * msg_len) - self.assertRaises(ValueError, cipher.encrypt, b'1' * (msg_len+16)) - self.assertRaises(ValueError, cipher.decrypt, b'1' * msg_len) - self.assertRaises(ValueError, cipher.decrypt, b'1' * (msg_len+16)) - - self.assertEqual(cipher.encrypt(b''), b'') - self.assertEqual(cipher.decrypt(b''), b'') - - -class TestOutput(unittest.TestCase): - - def __init__(self, use_aesni): - unittest.TestCase.__init__(self) - self.use_aesni = use_aesni - - def runTest(self): - # Encrypt/Decrypt data and test output parameter - - cipher = AES.new(b'4'*16, AES.MODE_ECB, use_aesni=self.use_aesni) - - 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(15) - self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output) - self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output) - - -def get_tests(config={}): - from Crypto.Util import _cpu_features - from .common import make_block_tests - - tests = make_block_tests(AES, "AES", test_data, {'use_aesni': False}) - tests += [ TestMultipleBlocks(False) ] - tests += [ TestIncompleteBlocks(False) ] - if _cpu_features.have_aes_ni(): - # Run tests with AES-NI instructions if they are available. - tests += make_block_tests(AES, "AESNI", test_data, {'use_aesni': True}) - tests += [ TestMultipleBlocks(True) ] - tests += [ TestIncompleteBlocks(True) ] - tests += [ TestOutput(True) ] - else: - print("Skipping AESNI tests") - 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: diff --git a/Crypto/SelfTest/Cipher/test_ARC2.py b/Crypto/SelfTest/Cipher/test_ARC2.py deleted file mode 100644 index fd9448c..0000000 --- a/Crypto/SelfTest/Cipher/test_ARC2.py +++ /dev/null @@ -1,167 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Cipher/ARC2.py: Self-test for the Alleged-RC2 cipher -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# 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: diff --git a/Crypto/SelfTest/Cipher/test_ARC4.py b/Crypto/SelfTest/Cipher/test_ARC4.py deleted file mode 100644 index 856cf4a..0000000 --- a/Crypto/SelfTest/Cipher/test_ARC4.py +++ /dev/null @@ -1,466 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Cipher/ARC4.py: Self-test for the Alleged-RC4 cipher -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-test suite for Crypto.Cipher.ARC4""" - -__revision__ = "$Id$" - -from Crypto.Util.py3compat import * -from Crypto.SelfTest.st_common import * -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"), -] - -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.assertEquals(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.assertEquals(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.assertEquals(pt_drop, pt) - - -class KeyLength(unittest.TestCase): - - def runTest(self): - self.assertRaises(ValueError, ARC4.new, bchr(0) * 4) - self.assertRaises(ValueError, ARC4.new, bchr(0) * 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__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') - -# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/Crypto/SelfTest/Cipher/test_Blowfish.py b/Crypto/SelfTest/Cipher/test_Blowfish.py deleted file mode 100644 index 4ce3a41..0000000 --- a/Crypto/SelfTest/Cipher/test_Blowfish.py +++ /dev/null @@ -1,160 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Cipher/test_Blowfish.py: Self-test for the Blowfish cipher -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# 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') diff --git a/Crypto/SelfTest/Cipher/test_CAST.py b/Crypto/SelfTest/Cipher/test_CAST.py deleted file mode 100644 index ff13bd4..0000000 --- a/Crypto/SelfTest/Cipher/test_CAST.py +++ /dev/null @@ -1,101 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Cipher/CAST.py: Self-test for the CAST-128 (CAST5) cipher -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# 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') diff --git a/Crypto/SelfTest/Cipher/test_CBC.py b/Crypto/SelfTest/Cipher/test_CBC.py deleted file mode 100644 index c82e8e5..0000000 --- a/Crypto/SelfTest/Cipher/test_CBC.py +++ /dev/null @@ -1,555 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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.assertEquals(ct, cipher.encrypt(self.data_128)) - - cipher = AES.new(self.key_128, self.aes_mode, IV=self.iv_128) - self.assertEquals(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" * 16 - 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" * 16 - 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' * 16 - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - ct = cipher.encrypt(pt) - - output = bytearray(16) - 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' * 16 - 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' * 16 - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - ct = cipher.encrypt(pt) - - output = memoryview(bytearray(16)) - 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): - - pt = b'5' * 16 - 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'*16) - - cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16) - - shorter_output = bytearray(15) - 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') diff --git a/Crypto/SelfTest/Cipher/test_CCM.py b/Crypto/SelfTest/Cipher/test_CCM.py deleted file mode 100644 index 5c84d44..0000000 --- a/Crypto/SelfTest/Cipher/test_CCM.py +++ /dev/null @@ -1,930 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2015, Legrandin -# 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_128 = get_tag_random("data_128", 16) - - 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_128) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - self.assertEquals(ct, cipher.encrypt(self.data_128)) - - 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_128) - 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_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_CCM, 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_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_128) - - def test_shorter_assoc_data_than_expected(self): - # With plaintext - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - assoc_len=17) - cipher.update(self.data_128) - self.assertRaises(ValueError, cipher.encrypt, self.data_128) - - # With empty plaintext - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - assoc_len=17) - cipher.update(self.data_128) - self.assertRaises(ValueError, cipher.digest) - - # With ciphertext - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - assoc_len=17) - cipher.update(self.data_128) - self.assertRaises(ValueError, cipher.decrypt, self.data_128) - - # With empty ciphertext - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - cipher.update(self.data_128) - mac = cipher.digest() - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - assoc_len=17) - cipher.update(self.data_128) - self.assertRaises(ValueError, cipher.verify, mac) - - def test_shorter_and_longer_plaintext_than_declared(self): - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - msg_len=17) - cipher.encrypt(self.data_128) - self.assertRaises(ValueError, cipher.digest) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - msg_len=15) - self.assertRaises(ValueError, cipher.encrypt, self.data_128) - - def test_shorter_ciphertext_than_declared(self): - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - ct, mac = cipher.encrypt_and_digest(self.data_128) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - msg_len=17) - cipher.decrypt(ct) - self.assertRaises(ValueError, cipher.verify, mac) - - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96, - msg_len=15) - 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.assertEquals(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_CCM, - 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_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_128) - 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_128, 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_128)) - data_mv = memoryview(bytearray(self.data_128)) - - cipher1 = AES.new(self.key_128, - AES.MODE_CCM, - 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_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_128)) - 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_128, pt_test) - - def test_output_param(self): - - pt = b'5' * 16 - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - tag = cipher.digest() - - output = bytearray(16) - 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' * 16 - cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - - output = memoryview(bytearray(16)) - 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_128 = get_tag_random("data_128", 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_128)): - # 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_128) - 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_128)): - 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_128) - 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_128) - cipher.verify(mac) - - def test_valid_full_path(self): - # Fixed authenticated data, fixed plaintext - for assoc_len in (None, len(self.data_128)): - for msg_len in (None, len(self.data_128)): - # 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_128) - ct = cipher.encrypt(self.data_128) - 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_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_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_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_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_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_CCM, 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_CCM, 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_CCM, 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_CCM, 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_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_128) - method = getattr(cipher, method_name) - method(self.data_128) - self.assertRaises(TypeError, method, self.data_128) - - 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_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_CCM, 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_CCM, 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_CCM, 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_CCM, 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_CCM, nonce=self.nonce_96) - cipher.decrypt_and_verify(ct, mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data_128) - - -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') diff --git a/Crypto/SelfTest/Cipher/test_CFB.py b/Crypto/SelfTest/Cipher/test_CFB.py deleted file mode 100644 index cb0c352..0000000 --- a/Crypto/SelfTest/Cipher/test_CFB.py +++ /dev/null @@ -1,411 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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') diff --git a/Crypto/SelfTest/Cipher/test_CTR.py b/Crypto/SelfTest/Cipher/test_CTR.py deleted file mode 100644 index ed367f8..0000000 --- a/Crypto/SelfTest/Cipher/test_CTR.py +++ /dev/null @@ -1,471 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2015, Legrandin -# 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.failIf(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' * 16 - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - ct = cipher.encrypt(pt) - - output = bytearray(16) - 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' * 16 - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - ct = cipher.encrypt(pt) - - output = memoryview(bytearray(16)) - 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): - - pt = b'5' * 16 - 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'*16) - - cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16) - - shorter_output = bytearray(15) - 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') diff --git a/Crypto/SelfTest/Cipher/test_ChaCha20.py b/Crypto/SelfTest/Cipher/test_ChaCha20.py deleted file mode 100644 index 2b8de20..0000000 --- a/Crypto/SelfTest/Cipher/test_ChaCha20.py +++ /dev/null @@ -1,529 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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.assertEquals(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.assertEquals(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' * 16 - ct = cipher.encrypt(pt) - - output = bytearray(16) - 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(16)) - 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'*16) - - cipher = ChaCha20.new(key=key, nonce=nonce) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16) - - shorter_output = bytearray(7) - - 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') diff --git a/Crypto/SelfTest/Cipher/test_ChaCha20_Poly1305.py b/Crypto/SelfTest/Cipher/test_ChaCha20_Poly1305.py deleted file mode 100644 index f7baad5..0000000 --- a/Crypto/SelfTest/Cipher/test_ChaCha20_Poly1305.py +++ /dev/null @@ -1,770 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2018, Helder Eijs -# 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._file_system import pycryptodome_filename -from Crypto.Util.strxor import strxor - - -def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) - - -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.assertEquals(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.failIf(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.assertEquals(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_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') diff --git a/Crypto/SelfTest/Cipher/test_DES.py b/Crypto/SelfTest/Cipher/test_DES.py deleted file mode 100644 index ee261bc..0000000 --- a/Crypto/SelfTest/Cipher/test_DES.py +++ /dev/null @@ -1,374 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Cipher/DES.py: Self-test for the (Single) DES cipher -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# 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: diff --git a/Crypto/SelfTest/Cipher/test_DES3.py b/Crypto/SelfTest/Cipher/test_DES3.py deleted file mode 100644 index 8d6a648..0000000 --- a/Crypto/SelfTest/Cipher/test_DES3.py +++ /dev/null @@ -1,195 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Cipher/DES3.py: Self-test for the Triple-DES cipher -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# 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: diff --git a/Crypto/SelfTest/Cipher/test_EAX.py b/Crypto/SelfTest/Cipher/test_EAX.py deleted file mode 100644 index ad88262..0000000 --- a/Crypto/SelfTest/Cipher/test_EAX.py +++ /dev/null @@ -1,772 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2015, Legrandin -# 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.assertEquals(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=3) - 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(5, 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.assertEquals(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' * 16 - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - tag = cipher.digest() - - output = bytearray(16) - 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' * 16 - cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - - output = memoryview(bytearray(16)) - 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): - - pt = b'5' * 16 - 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'*16) - - cipher = AES.new(self.key_128, AES.MODE_EAX, 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_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') diff --git a/Crypto/SelfTest/Cipher/test_GCM.py b/Crypto/SelfTest/Cipher/test_GCM.py deleted file mode 100644 index 5e7694f..0000000 --- a/Crypto/SelfTest/Cipher/test_GCM.py +++ /dev/null @@ -1,950 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2015, Legrandin -# 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_128 = get_tag_random("data_128", 16) - - 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_128) - - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - self.assertEquals(ct, cipher.encrypt(self.data_128)) - - 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_128) - 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_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_GCM, 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_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.assertEquals(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_GCM, - 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_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_128) - 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_128, 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_128)) - data_mv = memoryview(bytearray(self.data_128)) - - cipher1 = AES.new(self.key_128, - AES.MODE_GCM, - 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_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_128)) - 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_128, pt_test) - - def test_output_param(self): - - pt = b'5' * 16 - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - tag = cipher.digest() - - output = bytearray(16) - 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' * 16 - cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96) - ct = cipher.encrypt(pt) - - output = memoryview(bytearray(16)) - 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): - - pt = b'5' * 16 - 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'*16) - - cipher = AES.new(self.key_128, AES.MODE_GCM, 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_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_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_GCM, - 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_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_128) - 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_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_GCM, - 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_GCM, - 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_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_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_GCM, - 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_GCM, 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_GCM, 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_GCM, 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_GCM, 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_GCM, - 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_GCM, 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_GCM, 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_GCM, 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_GCM, 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_GCM, nonce=self.nonce_96) - cipher.decrypt_and_verify(ct, mac) - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data_128) - - -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') diff --git a/Crypto/SelfTest/Cipher/test_OCB.py b/Crypto/SelfTest/Cipher/test_OCB.py deleted file mode 100644 index c1baab3..0000000 --- a/Crypto/SelfTest/Cipher/test_OCB.py +++ /dev/null @@ -1,742 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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.Util.number import long_to_bytes -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_128 = get_tag_random("data_128", 16) - - 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_128) - - cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96) - self.assertEquals(ct, cipher.encrypt(self.data_128)) - - 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_128[:length]) - - self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_OCB, - nonce=self.data_128) - - 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_128) - 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_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_OCB, 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_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.assertEquals(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_OCB, - nonce=self.nonce_96) - cipher1.update(self.data_128) - ct = cipher1.encrypt(self.data_128) + 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_128) - 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_128, 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_128)) - data_mv = memoryview(bytearray(self.data_128)) - - cipher1 = AES.new(self.key_128, - AES.MODE_OCB, - nonce=self.nonce_96) - cipher1.update(self.data_128) - ct = cipher1.encrypt(self.data_128) + 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_128)) - 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_128, pt_test) - - -class OcbFSMTests(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->ENCRYPT(NONE)->DIGEST - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - ct = cipher.encrypt(self.data_128) - 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_128) - 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_128) - 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_128) - 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_128) - ct = cipher.encrypt(self.data_128) - 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_128) - cipher.decrypt(ct) - cipher.decrypt() - cipher.verify(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_128) - cipher.encrypt(self.data_128) - cipher.encrypt() - self.assertRaises(TypeError, cipher.encrypt, self.data_128) - - def test_invalid_decrypt_after_final(self): - cipher = AES.new(self.key_128, AES.MODE_OCB, - nonce=self.nonce_96) - cipher.update(self.data_128) - cipher.decrypt(self.data_128) - cipher.decrypt() - self.assertRaises(TypeError, cipher.decrypt, self.data_128) - - 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_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_OCB, - 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) - 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_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_OCB, 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_OCB, 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_OCB, 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_OCB, - 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_OCB, nonce=self.nonce_96) - cipher.encrypt(self.data_128) - cipher.encrypt() - cipher.digest() - self.assertRaises(TypeError, getattr(cipher, method_name), - self.data_128) - - cipher = AES.new(self.key_128, AES.MODE_OCB, 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_OCB, nonce=self.nonce_96) - ct = cipher.encrypt(self.data_128) - 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_128) - - 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_128) - - -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.assertEquals(ct, ct2) - self.assertEquals(mac_tag, cipher.digest()) - - cipher = AES.new(key, AES.MODE_OCB, nonce=nonce) - cipher.update(aad) - pt2 = cipher.decrypt(ct) + cipher.decrypt() - self.assertEquals(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.assertEquals(ct, ct2) - self.assertEquals(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.assertEquals(pt, pt2) - cipher.verify(mac_tag) - - def test3(self): - - for keylen, taglen, result in self.tv3: - - 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, 12) - 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, 12) - 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, 12) - 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, 12) - cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8) - cipher.update(C) - result2 = cipher.encrypt() + cipher.digest() - self.assertEquals(unhexlify(b(result)), result2) - - -def get_tests(config={}): - tests = [] - tests += list_test_cases(OcbTests) - tests += list_test_cases(OcbFSMTests) - tests += list_test_cases(OcbRfc7253Test) - return tests - - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/Cipher/test_OFB.py b/Crypto/SelfTest/Cipher/test_OFB.py deleted file mode 100644 index ec145ad..0000000 --- a/Crypto/SelfTest/Cipher/test_OFB.py +++ /dev/null @@ -1,238 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2015, Legrandin -# 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') diff --git a/Crypto/SelfTest/Cipher/test_OpenPGP.py b/Crypto/SelfTest/Cipher/test_OpenPGP.py deleted file mode 100644 index e6cae67..0000000 --- a/Crypto/SelfTest/Cipher/test_OpenPGP.py +++ /dev/null @@ -1,218 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2015, Legrandin -# 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') diff --git a/Crypto/SelfTest/Cipher/test_SIV.py b/Crypto/SelfTest/Cipher/test_SIV.py deleted file mode 100644 index 421c9eb..0000000 --- a/Crypto/SelfTest/Cipher/test_SIV.py +++ /dev/null @@ -1,551 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2015, Legrandin -# 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_128 = get_tag_random("data_128", 16) - - 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_128) - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - ct2, tag2 = cipher.encrypt_and_digest(self.data_128) - self.assertEquals(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.failIf(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_128) - self.assertRaises(TypeError, cipher.decrypt, self.data_128) - - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - cipher.encrypt_and_digest(self.data_128) - self.assertRaises(TypeError, cipher.decrypt_and_verify, - self.data_128, self.data_128) - - 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_128) - 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_128) - - 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_128) - header = bytearray(self.data_128) - - cipher1 = AES.new(self.key_256, - AES.MODE_SIV, - nonce=self.nonce_96) - cipher1.update(self.data_128) - ct, tag = cipher1.encrypt_and_digest(self.data_128) - - 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_128) - 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_128, pt_test) - - def test_memoryview(self): - - # Encrypt - key = memoryview(bytearray(self.key_256)) - nonce = memoryview(bytearray(self.nonce_96)) - data = memoryview(bytearray(self.data_128)) - header = memoryview(bytearray(self.data_128)) - - cipher1 = AES.new(self.key_256, - AES.MODE_SIV, - nonce=self.nonce_96) - cipher1.update(self.data_128) - ct, tag = cipher1.encrypt_and_digest(self.data_128) - - 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_128)) - 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_128, pt_test) - - def test_output_param(self): - - pt = b'5' * 16 - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - ct, tag = cipher.encrypt_and_digest(pt) - - output = bytearray(16) - 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' * 16 - cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96) - ct, tag = cipher.encrypt_and_digest(pt) - - output = memoryview(bytearray(16)) - 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): - - pt = b'5' * 16 - 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'*16) - - 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'*16) - - shorter_output = bytearray(15) - 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_128 = get_tag_random("data_128", 16) - - 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_128) - 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_128) - 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_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_256, AES.MODE_SIV, 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_256, AES.MODE_SIV, 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_256, AES.MODE_SIV, 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_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_128) - 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_128) - - 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') diff --git a/Crypto/SelfTest/Cipher/test_Salsa20.py b/Crypto/SelfTest/Cipher/test_Salsa20.py deleted file mode 100644 index fdcb072..0000000 --- a/Crypto/SelfTest/Cipher/test_Salsa20.py +++ /dev/null @@ -1,367 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Cipher/Salsa20.py: Self-test for the Salsa20 stream cipher -# -# Written in 2013 by Fabrizio Tarizzo -# -# =================================================================== -# 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' * 16 - ct = cipher.encrypt(pt) - - output = bytearray(16) - 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(16)) - 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'*16) - - cipher = Salsa20.new(key=key, nonce=nonce) - self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16) - - shorter_output = bytearray(7) - - 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: diff --git a/Crypto/SelfTest/Cipher/test_pkcs1_15.py b/Crypto/SelfTest/Cipher/test_pkcs1_15.py deleted file mode 100644 index e122971..0000000 --- a/Crypto/SelfTest/Cipher/test_pkcs1_15.py +++ /dev/null @@ -1,252 +0,0 @@ -# -*- 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 json -import unittest -from binascii import unhexlify - -from Crypto.PublicKey import RSA -from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex -from Crypto import Random -from Crypto.Cipher import PKCS1_v1_5 as PKCS -from Crypto.Util.py3compat import 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: - # Build the key - key = RSA.importKey(test[0]) - # The real test - cipher = PKCS.new(key) - pt = cipher.decrypt(t2b(test[2]), "---") - self.assertEqual(pt, b(test[1])) - - def testVerify2(self): - # Verify that decryption fails if ciphertext is not as long as - # RSA modulus - cipher = PKCS.new(self.key1024) - self.assertRaises(ValueError, cipher.decrypt, '\x00'*127, "---") - self.assertRaises(ValueError, cipher.decrypt, '\x00'*129, "---") - - # Verify that decryption fails if there are less then 8 non-zero padding - # bytes - pt = b('\x00\x02' + '\xFF'*7 + '\x00' + '\x45'*118) - pt_int = bytes_to_long(pt) - ct_int = self.key1024._encrypt(pt_int) - ct = long_to_bytes(ct_int, 128) - self.assertEqual("---", cipher.decrypt(ct, "---")) - - def testEncryptVerify1(self): - # Encrypt/Verify messages of length [0..RSAlen-11] - # and therefore padding [8..117] - for pt_len in range(0,128-11+1): - pt = self.rng(pt_len) - cipher = PKCS.new(self.key1024) - ct = cipher.encrypt(pt) - pt2 = cipher.decrypt(ct, "---") - self.assertEqual(pt,pt2) - - def 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']) - - 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 - - cipher = PKCS.new(tv.rsa_key) - try: - pt = cipher.decrypt(tv.ct, sentinel=b'---') - except ValueError: - assert not tv.valid - else: - if pt == b'---': - 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__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') - -# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/Crypto/SelfTest/Cipher/test_pkcs1_oaep.py b/Crypto/SelfTest/Cipher/test_pkcs1_oaep.py deleted file mode 100644 index 1711581..0000000 --- a/Crypto/SelfTest/Cipher/test_pkcs1_oaep.py +++ /dev/null @@ -1,506 +0,0 @@ -# -*- 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: diff --git a/Crypto/SelfTest/Hash/__init__.py b/Crypto/SelfTest/Hash/__init__.py deleted file mode 100644 index 1933f2a..0000000 --- a/Crypto/SelfTest/Hash/__init__.py +++ /dev/null @@ -1,61 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Hash/__init__.py: Self-test for hash modules -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-test for hash modules""" - -__revision__ = "$Id$" - -def get_tests(config={}): - tests = [] - from Crypto.SelfTest.Hash import test_HMAC; tests += test_HMAC.get_tests(config=config) - from Crypto.SelfTest.Hash import test_CMAC; tests += test_CMAC.get_tests(config=config) - from Crypto.SelfTest.Hash import test_MD2; tests += test_MD2.get_tests(config=config) - from Crypto.SelfTest.Hash import test_MD4; tests += test_MD4.get_tests(config=config) - from Crypto.SelfTest.Hash import test_MD5; tests += test_MD5.get_tests(config=config) - from Crypto.SelfTest.Hash import test_RIPEMD160; tests += test_RIPEMD160.get_tests(config=config) - from Crypto.SelfTest.Hash import test_SHA1; tests += test_SHA1.get_tests(config=config) - from Crypto.SelfTest.Hash import test_SHA256; tests += test_SHA256.get_tests(config=config) - from Crypto.SelfTest.Hash import test_SHA3_224; tests += test_SHA3_224.get_tests(config=config) - from Crypto.SelfTest.Hash import test_SHA3_256; tests += test_SHA3_256.get_tests(config=config) - from Crypto.SelfTest.Hash import test_SHA3_384; tests += test_SHA3_384.get_tests(config=config) - from Crypto.SelfTest.Hash import test_SHA3_512; tests += test_SHA3_512.get_tests(config=config) - from Crypto.SelfTest.Hash import test_keccak; tests += test_keccak.get_tests(config=config) - from Crypto.SelfTest.Hash import test_SHAKE; tests += test_SHAKE.get_tests(config=config) - try: - from Crypto.SelfTest.Hash import test_SHA224; tests += test_SHA224.get_tests(config=config) - from Crypto.SelfTest.Hash import test_SHA384; tests += test_SHA384.get_tests(config=config) - from Crypto.SelfTest.Hash import test_SHA512; tests += test_SHA512.get_tests(config=config) - except ImportError: - import sys - sys.stderr.write("SelfTest: warning: not testing SHA224/SHA384/SHA512 modules (not available)\n") - from Crypto.SelfTest.Hash import test_BLAKE2; tests += test_BLAKE2.get_tests(config=config) - from Crypto.SelfTest.Hash import test_Poly1305; tests += test_Poly1305.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: diff --git a/Crypto/SelfTest/Hash/__pycache__/__init__.cpython-36.pyc b/Crypto/SelfTest/Hash/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index 603e3fb..0000000 Binary files a/Crypto/SelfTest/Hash/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Hash/__pycache__/common.cpython-36.pyc b/Crypto/SelfTest/Hash/__pycache__/common.cpython-36.pyc deleted file mode 100644 index 4099ba9..0000000 Binary files a/Crypto/SelfTest/Hash/__pycache__/common.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Hash/__pycache__/test_BLAKE2.cpython-36.pyc b/Crypto/SelfTest/Hash/__pycache__/test_BLAKE2.cpython-36.pyc deleted file mode 100644 index 258d1f4..0000000 Binary files a/Crypto/SelfTest/Hash/__pycache__/test_BLAKE2.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Hash/__pycache__/test_CMAC.cpython-36.pyc b/Crypto/SelfTest/Hash/__pycache__/test_CMAC.cpython-36.pyc deleted file mode 100644 index c9e3453..0000000 Binary files a/Crypto/SelfTest/Hash/__pycache__/test_CMAC.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Hash/__pycache__/test_HMAC.cpython-36.pyc b/Crypto/SelfTest/Hash/__pycache__/test_HMAC.cpython-36.pyc deleted file mode 100644 index 56db0dc..0000000 Binary files a/Crypto/SelfTest/Hash/__pycache__/test_HMAC.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Hash/__pycache__/test_MD2.cpython-36.pyc b/Crypto/SelfTest/Hash/__pycache__/test_MD2.cpython-36.pyc deleted file mode 100644 index 9572fd7..0000000 Binary files a/Crypto/SelfTest/Hash/__pycache__/test_MD2.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Hash/__pycache__/test_MD4.cpython-36.pyc b/Crypto/SelfTest/Hash/__pycache__/test_MD4.cpython-36.pyc deleted file mode 100644 index f36517f..0000000 Binary files a/Crypto/SelfTest/Hash/__pycache__/test_MD4.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Hash/__pycache__/test_MD5.cpython-36.pyc b/Crypto/SelfTest/Hash/__pycache__/test_MD5.cpython-36.pyc deleted file mode 100644 index 0140b85..0000000 Binary files a/Crypto/SelfTest/Hash/__pycache__/test_MD5.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Hash/__pycache__/test_Poly1305.cpython-36.pyc b/Crypto/SelfTest/Hash/__pycache__/test_Poly1305.cpython-36.pyc deleted file mode 100644 index c4b20df..0000000 Binary files a/Crypto/SelfTest/Hash/__pycache__/test_Poly1305.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Hash/__pycache__/test_RIPEMD160.cpython-36.pyc b/Crypto/SelfTest/Hash/__pycache__/test_RIPEMD160.cpython-36.pyc deleted file mode 100644 index 1424cf1..0000000 Binary files a/Crypto/SelfTest/Hash/__pycache__/test_RIPEMD160.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Hash/__pycache__/test_SHA1.cpython-36.pyc b/Crypto/SelfTest/Hash/__pycache__/test_SHA1.cpython-36.pyc deleted file mode 100644 index fda4202..0000000 Binary files a/Crypto/SelfTest/Hash/__pycache__/test_SHA1.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Hash/__pycache__/test_SHA224.cpython-36.pyc b/Crypto/SelfTest/Hash/__pycache__/test_SHA224.cpython-36.pyc deleted file mode 100644 index 9691253..0000000 Binary files a/Crypto/SelfTest/Hash/__pycache__/test_SHA224.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Hash/__pycache__/test_SHA256.cpython-36.pyc b/Crypto/SelfTest/Hash/__pycache__/test_SHA256.cpython-36.pyc deleted file mode 100644 index 86aa81c..0000000 Binary files a/Crypto/SelfTest/Hash/__pycache__/test_SHA256.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Hash/__pycache__/test_SHA384.cpython-36.pyc b/Crypto/SelfTest/Hash/__pycache__/test_SHA384.cpython-36.pyc deleted file mode 100644 index b4a182e..0000000 Binary files a/Crypto/SelfTest/Hash/__pycache__/test_SHA384.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Hash/__pycache__/test_SHA3_224.cpython-36.pyc b/Crypto/SelfTest/Hash/__pycache__/test_SHA3_224.cpython-36.pyc deleted file mode 100644 index 07a9104..0000000 Binary files a/Crypto/SelfTest/Hash/__pycache__/test_SHA3_224.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Hash/__pycache__/test_SHA3_256.cpython-36.pyc b/Crypto/SelfTest/Hash/__pycache__/test_SHA3_256.cpython-36.pyc deleted file mode 100644 index a9de1e9..0000000 Binary files a/Crypto/SelfTest/Hash/__pycache__/test_SHA3_256.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Hash/__pycache__/test_SHA3_384.cpython-36.pyc b/Crypto/SelfTest/Hash/__pycache__/test_SHA3_384.cpython-36.pyc deleted file mode 100644 index 6710dc2..0000000 Binary files a/Crypto/SelfTest/Hash/__pycache__/test_SHA3_384.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Hash/__pycache__/test_SHA3_512.cpython-36.pyc b/Crypto/SelfTest/Hash/__pycache__/test_SHA3_512.cpython-36.pyc deleted file mode 100644 index 2b3807d..0000000 Binary files a/Crypto/SelfTest/Hash/__pycache__/test_SHA3_512.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Hash/__pycache__/test_SHA512.cpython-36.pyc b/Crypto/SelfTest/Hash/__pycache__/test_SHA512.cpython-36.pyc deleted file mode 100644 index fa2add9..0000000 Binary files a/Crypto/SelfTest/Hash/__pycache__/test_SHA512.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Hash/__pycache__/test_SHAKE.cpython-36.pyc b/Crypto/SelfTest/Hash/__pycache__/test_SHAKE.cpython-36.pyc deleted file mode 100644 index 9c87128..0000000 Binary files a/Crypto/SelfTest/Hash/__pycache__/test_SHAKE.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Hash/__pycache__/test_keccak.cpython-36.pyc b/Crypto/SelfTest/Hash/__pycache__/test_keccak.cpython-36.pyc deleted file mode 100644 index ac66eb6..0000000 Binary files a/Crypto/SelfTest/Hash/__pycache__/test_keccak.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Hash/common.py b/Crypto/SelfTest/Hash/common.py deleted file mode 100644 index b89db84..0000000 --- a/Crypto/SelfTest/Hash/common.py +++ /dev/null @@ -1,290 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Hash/common.py: Common code for Crypto.SelfTest.Hash -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# 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 re -import sys -import unittest -import binascii -import Crypto.Hash -from binascii import hexlify, unhexlify -from Crypto.Util.py3compat import b, tobytes -from Crypto.Util.strxor import strxor_c - -def t2b(hex_string): - shorter = re.sub(br'\s+', b'', tobytes(hex_string)) - return unhexlify(shorter) - - -class HashDigestSizeSelfTest(unittest.TestCase): - - def __init__(self, hashmod, description, expected, extra_params): - unittest.TestCase.__init__(self) - self.hashmod = hashmod - self.expected = expected - self.description = description - self.extra_params = extra_params - - def shortDescription(self): - return self.description - - def runTest(self): - if "truncate" not in self.extra_params: - self.failUnless(hasattr(self.hashmod, "digest_size")) - self.assertEquals(self.hashmod.digest_size, self.expected) - h = self.hashmod.new(**self.extra_params) - self.failUnless(hasattr(h, "digest_size")) - self.assertEquals(h.digest_size, self.expected) - - -class HashSelfTest(unittest.TestCase): - - def __init__(self, hashmod, description, expected, input, extra_params): - unittest.TestCase.__init__(self) - self.hashmod = hashmod - self.expected = expected.lower() - self.input = input - self.description = description - self.extra_params = extra_params - - def shortDescription(self): - return self.description - - def runTest(self): - h = self.hashmod.new(**self.extra_params) - h.update(self.input) - - out1 = binascii.b2a_hex(h.digest()) - out2 = h.hexdigest() - - h = self.hashmod.new(self.input, **self.extra_params) - - out3 = h.hexdigest() - out4 = binascii.b2a_hex(h.digest()) - - # PY3K: hexdigest() should return str(), and digest() bytes - self.assertEqual(self.expected, out1) # h = .new(); h.update(data); h.digest() - if sys.version_info[0] == 2: - self.assertEqual(self.expected, out2) # h = .new(); h.update(data); h.hexdigest() - self.assertEqual(self.expected, out3) # h = .new(data); h.hexdigest() - else: - self.assertEqual(self.expected.decode(), out2) # h = .new(); h.update(data); h.hexdigest() - self.assertEqual(self.expected.decode(), out3) # h = .new(data); h.hexdigest() - self.assertEqual(self.expected, out4) # h = .new(data); h.digest() - - # Verify that the .new() method produces a fresh hash object, except - # for MD5 and SHA1, which are hashlib objects. (But test any .new() - # method that does exist.) - if self.hashmod.__name__ not in ('Crypto.Hash.MD5', 'Crypto.Hash.SHA1') or hasattr(h, 'new'): - h2 = h.new() - h2.update(self.input) - out5 = binascii.b2a_hex(h2.digest()) - self.assertEqual(self.expected, out5) - - -class HashTestOID(unittest.TestCase): - def __init__(self, hashmod, oid, extra_params): - unittest.TestCase.__init__(self) - self.hashmod = hashmod - self.oid = oid - self.extra_params = extra_params - - def runTest(self): - h = self.hashmod.new(**self.extra_params) - self.assertEqual(h.oid, self.oid) - - -class ByteArrayTest(unittest.TestCase): - - def __init__(self, module, extra_params): - unittest.TestCase.__init__(self) - self.module = module - self.extra_params = extra_params - - def runTest(self): - data = b("\x00\x01\x02") - - # Data can be a bytearray (during initialization) - ba = bytearray(data) - - h1 = self.module.new(data, **self.extra_params) - h2 = self.module.new(ba, **self.extra_params) - ba[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) - - # Data can be a bytearray (during operation) - ba = bytearray(data) - - h1 = self.module.new(**self.extra_params) - h2 = self.module.new(**self.extra_params) - - h1.update(data) - h2.update(ba) - - ba[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) - - -class MemoryViewTest(unittest.TestCase): - - def __init__(self, module, extra_params): - unittest.TestCase.__init__(self) - self.module = module - self.extra_params = extra_params - - def runTest(self): - - data = b"\x00\x01\x02" - - def get_mv_ro(data): - return memoryview(data) - - def get_mv_rw(data): - return memoryview(bytearray(data)) - - for get_mv in get_mv_ro, get_mv_rw: - - # Data can be a memoryview (during initialization) - mv = get_mv(data) - - h1 = self.module.new(data, **self.extra_params) - h2 = self.module.new(mv, **self.extra_params) - if not mv.readonly: - mv[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) - - # Data can be a memoryview (during operation) - mv = get_mv(data) - - h1 = self.module.new(**self.extra_params) - h2 = self.module.new(**self.extra_params) - h1.update(data) - h2.update(mv) - if not mv.readonly: - mv[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) - - -class MACSelfTest(unittest.TestCase): - - def __init__(self, module, description, result, data, key, params): - unittest.TestCase.__init__(self) - self.module = module - self.result = t2b(result) - self.data = t2b(data) - self.key = t2b(key) - self.params = params - self.description = description - - def shortDescription(self): - return self.description - - def runTest(self): - - result_hex = hexlify(self.result) - - # Verify result - h = self.module.new(self.key, **self.params) - h.update(self.data) - self.assertEqual(self.result, h.digest()) - self.assertEqual(hexlify(self.result).decode('ascii'), h.hexdigest()) - - # Verify that correct MAC does not raise any exception - h.verify(self.result) - h.hexverify(result_hex) - - # Verify that incorrect MAC does raise ValueError exception - wrong_mac = strxor_c(self.result, 255) - self.assertRaises(ValueError, h.verify, wrong_mac) - self.assertRaises(ValueError, h.hexverify, "4556") - - # Verify again, with data passed to new() - h = self.module.new(self.key, self.data, **self.params) - self.assertEqual(self.result, h.digest()) - self.assertEqual(hexlify(self.result).decode('ascii'), h.hexdigest()) - - # Test .copy() - try: - h = self.module.new(self.key, self.data, **self.params) - h2 = h.copy() - h3 = h.copy() - - # Verify that changing the copy does not change the original - h2.update(b"bla") - self.assertEqual(h3.digest(), self.result) - - # Verify that both can reach the same state - h.update(b"bla") - self.assertEqual(h.digest(), h2.digest()) - except NotImplementedError: - pass - - # PY3K: Check that hexdigest() returns str and digest() returns bytes - self.assertTrue(isinstance(h.digest(), type(b""))) - self.assertTrue(isinstance(h.hexdigest(), type(""))) - - # PY3K: Check that .hexverify() accepts bytes or str - h.hexverify(h.hexdigest()) - h.hexverify(h.hexdigest().encode('ascii')) - - -def make_hash_tests(module, module_name, test_data, digest_size, oid=None, - extra_params={}): - tests = [] - for i in range(len(test_data)): - row = test_data[i] - (expected, input) = map(tobytes,row[0:2]) - if len(row) < 3: - description = repr(input) - else: - description = row[2] - name = "%s #%d: %s" % (module_name, i+1, description) - tests.append(HashSelfTest(module, name, expected, input, extra_params)) - - name = "%s #%d: digest_size" % (module_name, len(test_data) + 1) - tests.append(HashDigestSizeSelfTest(module, name, digest_size, extra_params)) - - if oid is not None: - tests.append(HashTestOID(module, oid, extra_params)) - - tests.append(ByteArrayTest(module, extra_params)) - - tests.append(MemoryViewTest(module, extra_params)) - - return tests - - -def make_mac_tests(module, module_name, test_data): - tests = [] - for i, row in enumerate(test_data): - if len(row) == 4: - (key, data, results, description, params) = list(row) + [ {} ] - else: - (key, data, results, description, params) = row - name = "%s #%d: %s" % (module_name, i+1, description) - tests.append(MACSelfTest(module, name, results, data, key, params)) - return tests - -# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/Crypto/SelfTest/Hash/test_BLAKE2.py b/Crypto/SelfTest/Hash/test_BLAKE2.py deleted file mode 100644 index f32163d..0000000 --- a/Crypto/SelfTest/Hash/test_BLAKE2.py +++ /dev/null @@ -1,482 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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 -import warnings -from binascii import unhexlify, hexlify - -from Crypto.Util.py3compat import tobytes -from Crypto.Util.strxor import strxor_c -from Crypto.SelfTest.st_common import list_test_cases - -from Crypto.Hash import BLAKE2b, BLAKE2s - - -class Blake2Test(unittest.TestCase): - - def test_new_positive(self): - - h = self.BLAKE2.new(digest_bits=self.max_bits) - for new_func in self.BLAKE2.new, h.new: - - for dbits in range(8, self.max_bits + 1, 8): - hobj = new_func(digest_bits=dbits) - self.assertEqual(hobj.digest_size, dbits // 8) - - for dbytes in range(1, self.max_bytes + 1): - hobj = new_func(digest_bytes=dbytes) - self.assertEqual(hobj.digest_size, dbytes) - - digest1 = new_func(data=b"\x90", digest_bytes=self.max_bytes).digest() - digest2 = new_func(digest_bytes=self.max_bytes).update(b"\x90").digest() - self.assertEqual(digest1, digest2) - - new_func(data=b"A", key=b"5", digest_bytes=self.max_bytes) - - hobj = h.new() - self.assertEqual(hobj.digest_size, self.max_bytes) - - def test_new_negative(self): - - h = self.BLAKE2.new(digest_bits=self.max_bits) - for new_func in self.BLAKE2.new, h.new: - self.assertRaises(TypeError, new_func, - digest_bytes=self.max_bytes, - digest_bits=self.max_bits) - self.assertRaises(ValueError, new_func, digest_bytes=0) - self.assertRaises(ValueError, new_func, - digest_bytes=self.max_bytes + 1) - self.assertRaises(ValueError, new_func, digest_bits=7) - self.assertRaises(ValueError, new_func, digest_bits=15) - self.assertRaises(ValueError, new_func, - digest_bits=self.max_bits + 1) - self.assertRaises(TypeError, new_func, - digest_bytes=self.max_bytes, - key=u"string") - self.assertRaises(TypeError, new_func, - digest_bytes=self.max_bytes, - data=u"string") - - def test_default_digest_size(self): - digest = self.BLAKE2.new(data=b'abc').digest() - self.assertEquals(len(digest), self.max_bytes) - - def test_update(self): - pieces = [b"\x0A" * 200, b"\x14" * 300] - h = self.BLAKE2.new(digest_bytes=self.max_bytes) - h.update(pieces[0]).update(pieces[1]) - digest = h.digest() - h = self.BLAKE2.new(digest_bytes=self.max_bytes) - h.update(pieces[0] + pieces[1]) - self.assertEqual(h.digest(), digest) - - def test_update_negative(self): - h = self.BLAKE2.new(digest_bytes=self.max_bytes) - self.assertRaises(TypeError, h.update, u"string") - - def test_digest(self): - h = self.BLAKE2.new(digest_bytes=self.max_bytes) - digest = h.digest() - - # hexdigest does not change the state - self.assertEqual(h.digest(), digest) - # digest returns a byte string - self.failUnless(isinstance(digest, type(b"digest"))) - - def test_update_after_digest(self): - msg = b"rrrrttt" - - # Normally, update() cannot be done after digest() - h = self.BLAKE2.new(digest_bits=256, data=msg[:4]) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - dig2 = self.BLAKE2.new(digest_bits=256, data=msg).digest() - - # With the proper flag, it is allowed - h = self.BLAKE2.new(digest_bits=256, data=msg[:4], update_after_digest=True) - self.assertEquals(h.digest(), dig1) - # ... and the subsequent digest applies to the entire message - # up to that point - h.update(msg[4:]) - self.assertEquals(h.digest(), dig2) - - def test_hex_digest(self): - mac = self.BLAKE2.new(digest_bits=self.max_bits) - digest = mac.digest() - hexdigest = mac.hexdigest() - - # hexdigest is equivalent to digest - self.assertEqual(hexlify(digest), tobytes(hexdigest)) - # hexdigest does not change the state - self.assertEqual(mac.hexdigest(), hexdigest) - # hexdigest returns a string - self.failUnless(isinstance(hexdigest, type("digest"))) - - def test_verify(self): - h = self.BLAKE2.new(digest_bytes=self.max_bytes, key=b"4") - mac = h.digest() - h.verify(mac) - wrong_mac = strxor_c(mac, 255) - self.assertRaises(ValueError, h.verify, wrong_mac) - - def test_hexverify(self): - h = self.BLAKE2.new(digest_bytes=self.max_bytes, key=b"4") - mac = h.hexdigest() - h.hexverify(mac) - self.assertRaises(ValueError, h.hexverify, "4556") - - def test_oid(self): - - prefix = "1.3.6.1.4.1.1722.12.2." + self.oid_variant + "." - - for digest_bits in self.digest_bits_oid: - h = self.BLAKE2.new(digest_bits=digest_bits) - self.assertEqual(h.oid, prefix + str(digest_bits // 8)) - - h = self.BLAKE2.new(digest_bits=digest_bits, key=b"secret") - self.assertRaises(AttributeError, lambda: h.oid) - - for digest_bits in (8, self.max_bits): - if digest_bits in self.digest_bits_oid: - continue - self.assertRaises(AttributeError, lambda: h.oid) - - def test_bytearray(self): - - key = b'0' * 16 - data = b"\x00\x01\x02" - - # Data and key can be a bytearray (during initialization) - key_ba = bytearray(key) - data_ba = bytearray(data) - - h1 = self.BLAKE2.new(data=data, key=key) - h2 = self.BLAKE2.new(data=data_ba, key=key_ba) - key_ba[:1] = b'\xFF' - data_ba[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) - - # Data can be a bytearray (during operation) - data_ba = bytearray(data) - - h1 = self.BLAKE2.new() - h2 = self.BLAKE2.new() - h1.update(data) - h2.update(data_ba) - data_ba[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) - - def test_memoryview(self): - - key = b'0' * 16 - data = b"\x00\x01\x02" - - def get_mv_ro(data): - return memoryview(data) - - def get_mv_rw(data): - return memoryview(bytearray(data)) - - for get_mv in (get_mv_ro, get_mv_rw): - - # Data and key can be a memoryview (during initialization) - key_mv = get_mv(key) - data_mv = get_mv(data) - - h1 = self.BLAKE2.new(data=data, key=key) - h2 = self.BLAKE2.new(data=data_mv, key=key_mv) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - key_mv[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) - - # Data can be a memoryview (during operation) - data_mv = get_mv(data) - - h1 = self.BLAKE2.new() - h2 = self.BLAKE2.new() - h1.update(data) - h2.update(data_mv) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) - - -class Blake2bTest(Blake2Test): - #: Module - BLAKE2 = BLAKE2b - #: Max output size (in bits) - max_bits = 512 - #: Max output size (in bytes) - max_bytes = 64 - #: Bit size of the digests for which an ASN OID exists - digest_bits_oid = (160, 256, 384, 512) - # http://tools.ietf.org/html/draft-saarinen-blake2-02 - oid_variant = "1" - - -class Blake2sTest(Blake2Test): - #: Module - BLAKE2 = BLAKE2s - #: Max output size (in bits) - max_bits = 256 - #: Max output size (in bytes) - max_bytes = 32 - #: Bit size of the digests for which an ASN OID exists - digest_bits_oid = (128, 160, 224, 256) - # http://tools.ietf.org/html/draft-saarinen-blake2-02 - oid_variant = "2" - - -class Blake2OfficialTestVector(unittest.TestCase): - - def _load_tests(self, test_vector_file): - expected = "in" - test_vectors = [] - with open(test_vector_file, "rt") as test_vector_fd: - for line_number, line in enumerate(test_vector_fd): - - if line.strip() == "" or line.startswith("#"): - continue - - res = re.match("%s:\t([0-9A-Fa-f]*)" % expected, line) - if not res: - raise ValueError("Incorrect test vector format (line %d)" - % line_number) - - if res.group(1): - bin_value = unhexlify(tobytes(res.group(1))) - else: - bin_value = b"" - if expected == "in": - input_data = bin_value - expected = "key" - elif expected == "key": - key = bin_value - expected = "hash" - else: - result = bin_value - expected = "in" - test_vectors.append((input_data, key, result)) - return test_vectors - - def setUp(self): - - dir_comps = ("Hash", self.name) - file_name = self.name.lower() + "-test.txt" - self.description = "%s tests" % self.name - - try: - import pycryptodome_test_vectors # type: ignore - except ImportError: - warnings.warn("Warning: skipping extended tests for %s" % self.name, - UserWarning) - self.test_vectors = [] - return - - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - self.test_vectors = self._load_tests(full_file_name) - - def runTest(self): - for (input_data, key, result) in self.test_vectors: - mac = self.BLAKE2.new(key=key, digest_bytes=self.max_bytes) - mac.update(input_data) - self.assertEqual(mac.digest(), result) - - -class Blake2bOfficialTestVector(Blake2OfficialTestVector): - #: Module - BLAKE2 = BLAKE2b - #: Hash name - name = "BLAKE2b" - #: Max digest size - max_bytes = 64 - - -class Blake2sOfficialTestVector(Blake2OfficialTestVector): - #: Module - BLAKE2 = BLAKE2s - #: Hash name - name = "BLAKE2s" - #: Max digest size - max_bytes = 32 - - -class Blake2TestVector1(unittest.TestCase): - - def _load_tests(self, test_vector_file): - test_vectors = [] - with open(test_vector_file, "rt") as test_vector_fd: - for line_number, line in enumerate(test_vector_fd): - if line.strip() == "" or line.startswith("#"): - continue - res = re.match("digest: ([0-9A-Fa-f]*)", line) - if not res: - raise ValueError("Incorrect test vector format (line %d)" - % line_number) - - test_vectors.append(unhexlify(tobytes(res.group(1)))) - return test_vectors - - def setUp(self): - dir_comps = ("Hash", self.name) - file_name = "tv1.txt" - self.description = "%s tests" % self.name - - try: - import pycryptodome_test_vectors - except ImportError: - warnings.warn("Warning: skipping extended tests for %s" % self.name, - UserWarning) - self.test_vectors = [] - return - - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - self.test_vectors = self._load_tests(full_file_name) - - def runTest(self): - - for tv in self.test_vectors: - digest_bytes = len(tv) - next_data = b"" - for _ in range(100): - h = self.BLAKE2.new(digest_bytes=digest_bytes) - h.update(next_data) - next_data = h.digest() + next_data - self.assertEqual(h.digest(), tv) - - -class Blake2bTestVector1(Blake2TestVector1): - #: Module - BLAKE2 = BLAKE2b - #: Hash name - name = "BLAKE2b" - - -class Blake2sTestVector1(Blake2TestVector1): - #: Module - BLAKE2 = BLAKE2s - #: Hash name - name = "BLAKE2s" - - -class Blake2TestVector2(unittest.TestCase): - - def _load_tests(self, test_vector_file): - test_vectors = [] - with open(test_vector_file, "rt") as test_vector_fd: - for line_number, line in enumerate(test_vector_fd): - if line.strip() == "" or line.startswith("#"): - continue - res = re.match(r"digest\(([0-9]+)\): ([0-9A-Fa-f]*)", line) - if not res: - raise ValueError("Incorrect test vector format (line %d)" - % line_number) - key_size = int(res.group(1)) - result = unhexlify(tobytes(res.group(2))) - test_vectors.append((key_size, result)) - return test_vectors - - def setUp(self): - dir_comps = ("Hash", self.name) - file_name = "tv2.txt" - self.description = "%s tests" % self.name - - try: - import pycryptodome_test_vectors # type: ignore - except ImportError: - warnings.warn("Warning: skipping extended tests for %s" % self.name, - UserWarning) - self.test_vectors = [] - return - - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - self.test_vectors = self._load_tests(full_file_name) - - def runTest(self): - - for key_size, result in self.test_vectors: - next_data = b"" - for _ in range(100): - h = self.BLAKE2.new(digest_bytes=self.max_bytes, - key=b"A" * key_size) - h.update(next_data) - next_data = h.digest() + next_data - self.assertEqual(h.digest(), result) - - -class Blake2bTestVector2(Blake2TestVector1): - #: Module - BLAKE2 = BLAKE2b - #: Hash name - name = "BLAKE2b" - #: Max digest size in bytes - max_bytes = 64 - - -class Blake2sTestVector2(Blake2TestVector1): - #: Module - BLAKE2 = BLAKE2s - #: Hash name - name = "BLAKE2s" - #: Max digest size in bytes - max_bytes = 32 - - -def get_tests(config={}): - tests = [] - - tests += list_test_cases(Blake2bTest) - tests.append(Blake2bOfficialTestVector()) - tests.append(Blake2bTestVector1()) - tests.append(Blake2bTestVector2()) - - tests += list_test_cases(Blake2sTest) - tests.append(Blake2sOfficialTestVector()) - tests.append(Blake2sTestVector1()) - tests.append(Blake2sTestVector2()) - - return tests - - -if __name__ == '__main__': - import unittest - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/Hash/test_CMAC.py b/Crypto/SelfTest/Hash/test_CMAC.py deleted file mode 100644 index 8cdbf09..0000000 --- a/Crypto/SelfTest/Hash/test_CMAC.py +++ /dev/null @@ -1,448 +0,0 @@ -# -# SelfTest/Hash/CMAC.py: Self-test for the CMAC module -# -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -"""Self-test suite for Crypto.Hash.CMAC""" - -import json -import unittest -from binascii import unhexlify - -from Crypto.Util.py3compat import tobytes - -from Crypto.Hash import CMAC -from Crypto.Cipher import AES, DES3 -from Crypto.Hash import SHAKE128 - -from Crypto.Util.strxor import strxor - -from Crypto.SelfTest.st_common import list_test_cases -from Crypto.SelfTest.loader import load_test_vectors_wycheproof - -# This is a list of (key, data, result, description, module) tuples. -test_data = [ - - ## Test vectors from RFC 4493 ## - ## The are also in NIST SP 800 38B D.2 ## - ( '2b7e151628aed2a6abf7158809cf4f3c', - '', - 'bb1d6929e95937287fa37d129b756746', - 'RFC 4493 #1', - AES - ), - - ( '2b7e151628aed2a6abf7158809cf4f3c', - '6bc1bee22e409f96e93d7e117393172a', - '070a16b46b4d4144f79bdd9dd04a287c', - 'RFC 4493 #2', - AES - ), - - ( '2b7e151628aed2a6abf7158809cf4f3c', - '6bc1bee22e409f96e93d7e117393172a'+ - 'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411', - 'dfa66747de9ae63030ca32611497c827', - 'RFC 4493 #3', - AES - ), - - ( '2b7e151628aed2a6abf7158809cf4f3c', - '6bc1bee22e409f96e93d7e117393172a'+ - 'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411e5fbc1191a0a52ef'+ - 'f69f2445df4f9b17ad2b417be66c3710', - '51f0bebf7e3b9d92fc49741779363cfe', - 'RFC 4493 #4', - AES - ), - - ## The rest of Appendix D of NIST SP 800 38B - ## was not totally correct. - ## Values in Examples 14, 15, 18, and 19 were wrong. - ## The updated test values are published in: - ## http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf - - ( '8e73b0f7da0e6452c810f32b809079e5'+ - '62f8ead2522c6b7b', - '', - 'd17ddf46adaacde531cac483de7a9367', - 'NIST SP 800 38B D.2 Example 5', - AES - ), - - ( '8e73b0f7da0e6452c810f32b809079e5'+ - '62f8ead2522c6b7b', - '6bc1bee22e409f96e93d7e117393172a', - '9e99a7bf31e710900662f65e617c5184', - 'NIST SP 800 38B D.2 Example 6', - AES - ), - - ( '8e73b0f7da0e6452c810f32b809079e5'+ - '62f8ead2522c6b7b', - '6bc1bee22e409f96e93d7e117393172a'+ - 'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411', - '8a1de5be2eb31aad089a82e6ee908b0e', - 'NIST SP 800 38B D.2 Example 7', - AES - ), - - ( '8e73b0f7da0e6452c810f32b809079e5'+ - '62f8ead2522c6b7b', - '6bc1bee22e409f96e93d7e117393172a'+ - 'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411e5fbc1191a0a52ef'+ - 'f69f2445df4f9b17ad2b417be66c3710', - 'a1d5df0eed790f794d77589659f39a11', - 'NIST SP 800 38B D.2 Example 8', - AES - ), - - ( '603deb1015ca71be2b73aef0857d7781'+ - '1f352c073b6108d72d9810a30914dff4', - '', - '028962f61b7bf89efc6b551f4667d983', - 'NIST SP 800 38B D.3 Example 9', - AES - ), - - ( '603deb1015ca71be2b73aef0857d7781'+ - '1f352c073b6108d72d9810a30914dff4', - '6bc1bee22e409f96e93d7e117393172a', - '28a7023f452e8f82bd4bf28d8c37c35c', - 'NIST SP 800 38B D.3 Example 10', - AES - ), - - ( '603deb1015ca71be2b73aef0857d7781'+ - '1f352c073b6108d72d9810a30914dff4', - '6bc1bee22e409f96e93d7e117393172a'+ - 'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411', - 'aaf3d8f1de5640c232f5b169b9c911e6', - 'NIST SP 800 38B D.3 Example 11', - AES - ), - - ( '603deb1015ca71be2b73aef0857d7781'+ - '1f352c073b6108d72d9810a30914dff4', - '6bc1bee22e409f96e93d7e117393172a'+ - 'ae2d8a571e03ac9c9eb76fac45af8e51'+ - '30c81c46a35ce411e5fbc1191a0a52ef'+ - 'f69f2445df4f9b17ad2b417be66c3710', - 'e1992190549f6ed5696a2c056c315410', - 'NIST SP 800 38B D.3 Example 12', - AES - ), - - ( '8aa83bf8cbda1062'+ - '0bc1bf19fbb6cd58'+ - 'bc313d4a371ca8b5', - '', - 'b7a688e122ffaf95', - 'NIST SP 800 38B D.4 Example 13', - DES3 - ), - - ( '8aa83bf8cbda1062'+ - '0bc1bf19fbb6cd58'+ - 'bc313d4a371ca8b5', - '6bc1bee22e409f96', - '8e8f293136283797', - 'NIST SP 800 38B D.4 Example 14', - DES3 - ), - - ( '8aa83bf8cbda1062'+ - '0bc1bf19fbb6cd58'+ - 'bc313d4a371ca8b5', - '6bc1bee22e409f96'+ - 'e93d7e117393172a'+ - 'ae2d8a57', - '743ddbe0ce2dc2ed', - 'NIST SP 800 38B D.4 Example 15', - DES3 - ), - - ( '8aa83bf8cbda1062'+ - '0bc1bf19fbb6cd58'+ - 'bc313d4a371ca8b5', - '6bc1bee22e409f96'+ - 'e93d7e117393172a'+ - 'ae2d8a571e03ac9c'+ - '9eb76fac45af8e51', - '33e6b1092400eae5', - 'NIST SP 800 38B D.4 Example 16', - DES3 - ), - - ( '4cf15134a2850dd5'+ - '8a3d10ba80570d38', - '', - 'bd2ebf9a3ba00361', - 'NIST SP 800 38B D.7 Example 17', - DES3 - ), - - ( '4cf15134a2850dd5'+ - '8a3d10ba80570d38', - '6bc1bee22e409f96', - '4ff2ab813c53ce83', - 'NIST SP 800 38B D.7 Example 18', - DES3 - ), - - ( '4cf15134a2850dd5'+ - '8a3d10ba80570d38', - '6bc1bee22e409f96'+ - 'e93d7e117393172a'+ - 'ae2d8a57', - '62dd1b471902bd4e', - 'NIST SP 800 38B D.7 Example 19', - DES3 - ), - - ( '4cf15134a2850dd5'+ - '8a3d10ba80570d38', - '6bc1bee22e409f96'+ - 'e93d7e117393172a'+ - 'ae2d8a571e03ac9c'+ - '9eb76fac45af8e51', - '31b1e431dabc4eb8', - 'NIST SP 800 38B D.7 Example 20', - DES3 - ), - -] - - -def get_tag_random(tag, length): - return SHAKE128.new(data=tobytes(tag)).read(length) - - -class TestCMAC(unittest.TestCase): - - def test_internal_caching(self): - """Verify that internal caching is implemented correctly""" - - data_to_mac = get_tag_random("data_to_mac", 128) - key = get_tag_random("key", 16) - ref_mac = CMAC.new(key, msg=data_to_mac, ciphermod=AES).digest() - - # Break up in chunks of different length - # The result must always be the same - for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128: - - chunks = [data_to_mac[i:i+chunk_length] for i in - range(0, len(data_to_mac), chunk_length)] - - mac = CMAC.new(key, ciphermod=AES) - for chunk in chunks: - mac.update(chunk) - self.assertEqual(ref_mac, mac.digest()) - - def test_update_after_digest(self): - msg = b"rrrrttt" - key = b"4" * 16 - - # Normally, update() cannot be done after digest() - h = CMAC.new(key, msg[:4], ciphermod=AES) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - dig2 = CMAC.new(key, msg, ciphermod=AES).digest() - - # With the proper flag, it is allowed - h2 = CMAC.new(key, msg[:4], ciphermod=AES, update_after_digest=True) - self.assertEquals(h2.digest(), dig1) - # ... and the subsequent digest applies to the entire message - # up to that point - h2.update(msg[4:]) - self.assertEquals(h2.digest(), dig2) - - -class ByteArrayTests(unittest.TestCase): - - def runTest(self): - - key = b"0" * 16 - data = b"\x00\x01\x02" - - # Data and key can be a bytearray (during initialization) - key_ba = bytearray(key) - data_ba = bytearray(data) - - h1 = CMAC.new(key, data, ciphermod=AES) - h2 = CMAC.new(key_ba, data_ba, ciphermod=AES) - key_ba[:1] = b'\xFF' - data_ba[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) - - # Data can be a bytearray (during operation) - key_ba = bytearray(key) - data_ba = bytearray(data) - - h1 = CMAC.new(key, ciphermod=AES) - h2 = CMAC.new(key, ciphermod=AES) - h1.update(data) - h2.update(data_ba) - data_ba[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) - - -class MemoryViewTests(unittest.TestCase): - - def runTest(self): - - key = b"0" * 16 - data = b"\x00\x01\x02" - - def get_mv_ro(data): - return memoryview(data) - - def get_mv_rw(data): - return memoryview(bytearray(data)) - - for get_mv in (get_mv_ro, get_mv_rw): - - # Data and key can be a memoryview (during initialization) - key_mv = get_mv(key) - data_mv = get_mv(data) - - h1 = CMAC.new(key, data, ciphermod=AES) - h2 = CMAC.new(key_mv, data_mv, ciphermod=AES) - if not data_mv.readonly: - key_mv[:1] = b'\xFF' - data_mv[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) - - # Data can be a memoryview (during operation) - data_mv = get_mv(data) - - h1 = CMAC.new(key, ciphermod=AES) - h2 = CMAC.new(key, ciphermod=AES) - h1.update(data) - h2.update(data_mv) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) - - -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(("Hash", "wycheproof"), - "aes_cmac_test.json", - "Wycheproof CMAC", - 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_create_mac(self, tv): - self._id = "Wycheproof MAC creation Test #" + str(tv.id) - - try: - tag = CMAC.new(tv.key, tv.msg, ciphermod=AES, mac_len=tv.tag_size).digest() - except ValueError as e: - if len(tv.key) not in (16, 24, 32) and "key length" in str(e): - return - raise e - if tv.valid: - self.assertEqual(tag, tv.tag) - self.warn(tv) - - def test_verify_mac(self, tv): - self._id = "Wycheproof MAC verification Test #" + str(tv.id) - - try: - mac = CMAC.new(tv.key, tv.msg, ciphermod=AES, mac_len=tv.tag_size) - except ValueError as e: - if len(tv.key) not in (16, 24, 32) and "key length" in str(e): - return - raise e - try: - mac.verify(tv.tag) - except ValueError: - assert not tv.valid - else: - assert tv.valid - self.warn(tv) - - def runTest(self): - - for tv in self.tv: - self.test_create_mac(tv) - self.test_verify_mac(tv) - - -def get_tests(config={}): - global test_data - import types - from .common import make_mac_tests - - wycheproof_warnings = config.get('wycheproof_warnings') - - # Add new() parameters to the back of each test vector - params_test_data = [] - for row in test_data: - t = list(row) - t[4] = dict(ciphermod=t[4]) - params_test_data.append(t) - - tests = make_mac_tests(CMAC, "CMAC", params_test_data) - tests.append(ByteArrayTests()) - tests.append(list_test_cases(TestCMAC)) - tests.append(MemoryViewTests()) - tests += [ TestVectorsWycheproof(wycheproof_warnings) ] - return tests - - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/Hash/test_HMAC.py b/Crypto/SelfTest/Hash/test_HMAC.py deleted file mode 100644 index 7be15be..0000000 --- a/Crypto/SelfTest/Hash/test_HMAC.py +++ /dev/null @@ -1,402 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Hash/HMAC.py: Self-test for the HMAC module -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-test suite for Crypto.Hash.HMAC""" - -import sys -import unittest -from binascii import hexlify -from Crypto.Util.py3compat import tostr, tobytes - -from Crypto.Hash import HMAC, MD5, SHA1, SHA256 -hash_modules = dict(MD5=MD5, SHA1=SHA1, SHA256=SHA256) - -try: - from Crypto.Hash import SHA224, SHA384, SHA512, RIPEMD160 - hash_modules.update(dict(SHA224=SHA224, SHA384=SHA384, SHA512=SHA512, - RIPEMD160=RIPEMD160)) -except ImportError: - sys.stderr.write("SelfTest: warning: not testing HMAC-SHA224/384/512" - " (not available)\n") - -default_hash = None - -def xl(text): - return tostr(hexlify(tobytes(text))) - -# This is a list of (key, data, results, description) tuples. -test_data = [ - ## Test vectors from RFC 2202 ## - # Test that the default hashmod is MD5 - ('0b' * 16, - '4869205468657265', - dict(default_hash='9294727a3638bb1c13f48ef8158bfc9d'), - 'default-is-MD5'), - - # Test case 1 (MD5) - ('0b' * 16, - '4869205468657265', - dict(MD5='9294727a3638bb1c13f48ef8158bfc9d'), - 'RFC 2202 #1-MD5 (HMAC-MD5)'), - - # Test case 1 (SHA1) - ('0b' * 20, - '4869205468657265', - dict(SHA1='b617318655057264e28bc0b6fb378c8ef146be00'), - 'RFC 2202 #1-SHA1 (HMAC-SHA1)'), - - # Test case 2 - ('4a656665', - '7768617420646f2079612077616e7420666f72206e6f7468696e673f', - dict(MD5='750c783e6ab0b503eaa86e310a5db738', - SHA1='effcdf6ae5eb2fa2d27416d5f184df9c259a7c79'), - 'RFC 2202 #2 (HMAC-MD5/SHA1)'), - - # Test case 3 (MD5) - ('aa' * 16, - 'dd' * 50, - dict(MD5='56be34521d144c88dbb8c733f0e8b3f6'), - 'RFC 2202 #3-MD5 (HMAC-MD5)'), - - # Test case 3 (SHA1) - ('aa' * 20, - 'dd' * 50, - dict(SHA1='125d7342b9ac11cd91a39af48aa17b4f63f175d3'), - 'RFC 2202 #3-SHA1 (HMAC-SHA1)'), - - # Test case 4 - ('0102030405060708090a0b0c0d0e0f10111213141516171819', - 'cd' * 50, - dict(MD5='697eaf0aca3a3aea3a75164746ffaa79', - SHA1='4c9007f4026250c6bc8414f9bf50c86c2d7235da'), - 'RFC 2202 #4 (HMAC-MD5/SHA1)'), - - # Test case 5 (MD5) - ('0c' * 16, - '546573742057697468205472756e636174696f6e', - dict(MD5='56461ef2342edc00f9bab995690efd4c'), - 'RFC 2202 #5-MD5 (HMAC-MD5)'), - - # Test case 5 (SHA1) - # NB: We do not implement hash truncation, so we only test the full hash here. - ('0c' * 20, - '546573742057697468205472756e636174696f6e', - dict(SHA1='4c1a03424b55e07fe7f27be1d58bb9324a9a5a04'), - 'RFC 2202 #5-SHA1 (HMAC-SHA1)'), - - # Test case 6 - ('aa' * 80, - '54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a' - + '65204b6579202d2048617368204b6579204669727374', - dict(MD5='6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd', - SHA1='aa4ae5e15272d00e95705637ce8a3b55ed402112'), - 'RFC 2202 #6 (HMAC-MD5/SHA1)'), - - # Test case 7 - ('aa' * 80, - '54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a' - + '65204b657920616e64204c6172676572205468616e204f6e6520426c6f636b2d' - + '53697a652044617461', - dict(MD5='6f630fad67cda0ee1fb1f562db3aa53e', - SHA1='e8e99d0f45237d786d6bbaa7965c7808bbff1a91'), - 'RFC 2202 #7 (HMAC-MD5/SHA1)'), - - ## Test vectors from RFC 4231 ## - # 4.2. Test Case 1 - ('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b', - '4869205468657265', - dict(SHA256=''' - b0344c61d8db38535ca8afceaf0bf12b - 881dc200c9833da726e9376c2e32cff7 - '''), - 'RFC 4231 #1 (HMAC-SHA256)'), - - # 4.3. Test Case 2 - Test with a key shorter than the length of the HMAC - # output. - ('4a656665', - '7768617420646f2079612077616e7420666f72206e6f7468696e673f', - dict(SHA256=''' - 5bdcc146bf60754e6a042426089575c7 - 5a003f089d2739839dec58b964ec3843 - '''), - 'RFC 4231 #2 (HMAC-SHA256)'), - - # 4.4. Test Case 3 - Test with a combined length of key and data that is - # larger than 64 bytes (= block-size of SHA-224 and SHA-256). - ('aa' * 20, - 'dd' * 50, - dict(SHA256=''' - 773ea91e36800e46854db8ebd09181a7 - 2959098b3ef8c122d9635514ced565fe - '''), - 'RFC 4231 #3 (HMAC-SHA256)'), - - # 4.5. Test Case 4 - Test with a combined length of key and data that is - # larger than 64 bytes (= block-size of SHA-224 and SHA-256). - ('0102030405060708090a0b0c0d0e0f10111213141516171819', - 'cd' * 50, - dict(SHA256=''' - 82558a389a443c0ea4cc819899f2083a - 85f0faa3e578f8077a2e3ff46729665b - '''), - 'RFC 4231 #4 (HMAC-SHA256)'), - - # 4.6. Test Case 5 - Test with a truncation of output to 128 bits. - # - # Not included because we do not implement hash truncation. - # - - # 4.7. Test Case 6 - Test with a key larger than 128 bytes (= block-size of - # SHA-384 and SHA-512). - ('aa' * 131, - '54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a' - + '65204b6579202d2048617368204b6579204669727374', - dict(SHA256=''' - 60e431591ee0b67f0d8a26aacbf5b77f - 8e0bc6213728c5140546040f0ee37f54 - '''), - 'RFC 4231 #6 (HMAC-SHA256)'), - - # 4.8. Test Case 7 - Test with a key and data that is larger than 128 bytes - # (= block-size of SHA-384 and SHA-512). - ('aa' * 131, - '5468697320697320612074657374207573696e672061206c6172676572207468' - + '616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074' - + '68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565' - + '647320746f20626520686173686564206265666f7265206265696e6720757365' - + '642062792074686520484d414320616c676f726974686d2e', - dict(SHA256=''' - 9b09ffa71b942fcb27635fbcd5b0e944 - bfdc63644f0713938a7f51535c3a35e2 - '''), - 'RFC 4231 #7 (HMAC-SHA256)'), - - # Test case 8 (SHA224) - ('4a656665', - '7768617420646f2079612077616e74' - + '20666f72206e6f7468696e673f', - dict(SHA224='a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44'), - 'RFC 4634 8.4 SHA224 (HMAC-SHA224)'), - - # Test case 9 (SHA384) - ('4a656665', - '7768617420646f2079612077616e74' - + '20666f72206e6f7468696e673f', - dict(SHA384='af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649'), - 'RFC 4634 8.4 SHA384 (HMAC-SHA384)'), - - # Test case 10 (SHA512) - ('4a656665', - '7768617420646f2079612077616e74' - + '20666f72206e6f7468696e673f', - dict(SHA512='164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737'), - 'RFC 4634 8.4 SHA512 (HMAC-SHA512)'), - - # Test case 11 (RIPEMD) - ('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b', - xl("Hi There"), - dict(RIPEMD160='24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668'), - 'RFC 2286 #1 (HMAC-RIPEMD)'), - - # Test case 12 (RIPEMD) - (xl("Jefe"), - xl("what do ya want for nothing?"), - dict(RIPEMD160='dda6c0213a485a9e24f4742064a7f033b43c4069'), - 'RFC 2286 #2 (HMAC-RIPEMD)'), - - # Test case 13 (RIPEMD) - ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', - 'dd' * 50, - dict(RIPEMD160='b0b105360de759960ab4f35298e116e295d8e7c1'), - 'RFC 2286 #3 (HMAC-RIPEMD)'), - - # Test case 14 (RIPEMD) - ('0102030405060708090a0b0c0d0e0f10111213141516171819', - 'cd' * 50, - dict(RIPEMD160='d5ca862f4d21d5e610e18b4cf1beb97a4365ecf4'), - 'RFC 2286 #4 (HMAC-RIPEMD)'), - - # Test case 15 (RIPEMD) - ('0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c', - xl("Test With Truncation"), - dict(RIPEMD160='7619693978f91d90539ae786500ff3d8e0518e39'), - 'RFC 2286 #5 (HMAC-RIPEMD)'), - - # Test case 16 (RIPEMD) - ('aa' * 80, - xl("Test Using Larger Than Block-Size Key - Hash Key First"), - dict(RIPEMD160='6466ca07ac5eac29e1bd523e5ada7605b791fd8b'), - 'RFC 2286 #6 (HMAC-RIPEMD)'), - - # Test case 17 (RIPEMD) - ('aa' * 80, - xl("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"), - dict(RIPEMD160='69ea60798d71616cce5fd0871e23754cd75d5a0a'), - 'RFC 2286 #7 (HMAC-RIPEMD)'), - -] - - -class HMAC_Module_and_Instance_Test(unittest.TestCase): - """Test the HMAC construction and verify that it does not - matter if you initialize it with a hash module or - with an hash instance. - - See https://bugs.launchpad.net/pycrypto/+bug/1209399 - """ - - def __init__(self, hashmods): - """Initialize the test with a dictionary of hash modules - indexed by their names""" - - unittest.TestCase.__init__(self) - self.hashmods = hashmods - self.description = "" - - def shortDescription(self): - return self.description - - def runTest(self): - key = b"\x90\x91\x92\x93" * 4 - payload = b"\x00" * 100 - - for hashname, hashmod in self.hashmods.items(): - if hashmod is None: - continue - self.description = "Test HMAC in combination with " + hashname - one = HMAC.new(key, payload, hashmod).digest() - two = HMAC.new(key, payload, hashmod.new()).digest() - self.assertEqual(one, two) - - -class HMAC_None(unittest.TestCase): - - def runTest(self): - - key = b"\x04" * 20 - one = HMAC.new(key, b"", SHA1).digest() - two = HMAC.new(key, None, SHA1).digest() - self.assertEqual(one, two) - - -class ByteArrayTests(unittest.TestCase): - - def runTest(self): - - key = b"0" * 16 - data = b"\x00\x01\x02" - - # Data and key can be a bytearray (during initialization) - key_ba = bytearray(key) - data_ba = bytearray(data) - - h1 = HMAC.new(key, data) - h2 = HMAC.new(key_ba, data_ba) - key_ba[:1] = b'\xFF' - data_ba[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) - - # Data can be a bytearray (during operation) - key_ba = bytearray(key) - data_ba = bytearray(data) - - h1 = HMAC.new(key) - h2 = HMAC.new(key) - h1.update(data) - h2.update(data_ba) - data_ba[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) - - -class MemoryViewTests(unittest.TestCase): - - def runTest(self): - - key = b"0" * 16 - data = b"\x00\x01\x02" - - def get_mv_ro(data): - return memoryview(data) - - def get_mv_rw(data): - return memoryview(bytearray(data)) - - for get_mv in (get_mv_ro, get_mv_rw): - - # Data and key can be a memoryview (during initialization) - key_mv = get_mv(key) - data_mv = get_mv(data) - - h1 = HMAC.new(key, data) - h2 = HMAC.new(key_mv, data_mv) - if not data_mv.readonly: - key_mv[:1] = b'\xFF' - data_mv[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) - - # Data can be a memoryview (during operation) - data_mv = get_mv(data) - - h1 = HMAC.new(key) - h2 = HMAC.new(key) - h1.update(data) - h2.update(data_mv) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - self.assertEqual(h1.digest(), h2.digest()) - - -def get_tests(config={}): - global test_data - import types - from .common import make_mac_tests - - # A test vector contains multiple results, each one for a - # different hash algorithm. - # Here we expand each test vector into multiple ones, - # and add the relevant parameters that will be passed to new() - exp_test_data = [] - for row in test_data: - for modname in row[2].keys(): - t = list(row) - t[2] = row[2][modname] - try: - t.append(dict(digestmod=globals()[modname])) - exp_test_data.append(t) - except AttributeError: - sys.stderr.write("SelfTest: warning: not testing HMAC-%s" - " (not available)\n" % modname) - tests = make_mac_tests(HMAC, "HMAC", exp_test_data) - tests.append(HMAC_Module_and_Instance_Test(hash_modules)) - tests.append(HMAC_None()) - - tests.append(ByteArrayTests()) - tests.append(MemoryViewTests()) - - return tests - - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/Hash/test_MD2.py b/Crypto/SelfTest/Hash/test_MD2.py deleted file mode 100644 index 9375168..0000000 --- a/Crypto/SelfTest/Hash/test_MD2.py +++ /dev/null @@ -1,62 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Hash/MD2.py: Self-test for the MD2 hash function -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-test suite for Crypto.Hash.MD2""" - -from Crypto.Util.py3compat import * - -# This is a list of (expected_result, input[, description]) tuples. -test_data = [ - # Test vectors from RFC 1319 - ('8350e5a3e24c153df2275c9f80692773', '', "'' (empty string)"), - ('32ec01ec4a6dac72c0ab96fb34c0b5d1', 'a'), - ('da853b0d3f88d99b30283a69e6ded6bb', 'abc'), - ('ab4f496bfb2a530b219ff33031fe06b0', 'message digest'), - - ('4e8ddff3650292ab5a4108c3aa47940b', 'abcdefghijklmnopqrstuvwxyz', - 'a-z'), - - ('da33def2a42df13975352846c30338cd', - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', - 'A-Z, a-z, 0-9'), - - ('d5976f79d83d3a0dc9806c3c66f3efd8', - '1234567890123456789012345678901234567890123456' - + '7890123456789012345678901234567890', - "'1234567890' * 8"), -] - -def get_tests(config={}): - from Crypto.Hash import MD2 - from .common import make_hash_tests - return make_hash_tests(MD2, "MD2", test_data, - digest_size=16, - oid="1.2.840.113549.2.2") - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') - -# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/Crypto/SelfTest/Hash/test_MD4.py b/Crypto/SelfTest/Hash/test_MD4.py deleted file mode 100644 index 17b48a7..0000000 --- a/Crypto/SelfTest/Hash/test_MD4.py +++ /dev/null @@ -1,64 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Hash/MD4.py: Self-test for the MD4 hash function -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-test suite for Crypto.Hash.MD4""" - -__revision__ = "$Id$" - -from Crypto.Util.py3compat import * - -# This is a list of (expected_result, input[, description]) tuples. -test_data = [ - # Test vectors from RFC 1320 - ('31d6cfe0d16ae931b73c59d7e0c089c0', '', "'' (empty string)"), - ('bde52cb31de33e46245e05fbdbd6fb24', 'a'), - ('a448017aaf21d8525fc10ae87aa6729d', 'abc'), - ('d9130a8164549fe818874806e1c7014b', 'message digest'), - - ('d79e1c308aa5bbcdeea8ed63df412da9', 'abcdefghijklmnopqrstuvwxyz', - 'a-z'), - - ('043f8582f241db351ce627e153e7f0e4', - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', - 'A-Z, a-z, 0-9'), - - ('e33b4ddc9c38f2199c3e7b164fcc0536', - '1234567890123456789012345678901234567890123456' - + '7890123456789012345678901234567890', - "'1234567890' * 8"), -] - -def get_tests(config={}): - from Crypto.Hash import MD4 - from .common import make_hash_tests - return make_hash_tests(MD4, "MD4", test_data, - digest_size=16, - oid="1.2.840.113549.2.4") - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') - -# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/Crypto/SelfTest/Hash/test_MD5.py b/Crypto/SelfTest/Hash/test_MD5.py deleted file mode 100644 index 830ace7..0000000 --- a/Crypto/SelfTest/Hash/test_MD5.py +++ /dev/null @@ -1,94 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Hash/MD5.py: Self-test for the MD5 hash function -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-test suite for Crypto.Hash.MD5""" - -from Crypto.Util.py3compat import * -from Crypto.Hash import MD5 -from binascii import unhexlify -import unittest -from Crypto.SelfTest.st_common import list_test_cases - - -# This is a list of (expected_result, input[, description]) tuples. -test_data = [ - # Test vectors from RFC 1321 - ('d41d8cd98f00b204e9800998ecf8427e', '', "'' (empty string)"), - ('0cc175b9c0f1b6a831c399e269772661', 'a'), - ('900150983cd24fb0d6963f7d28e17f72', 'abc'), - ('f96b697d7cb7938d525a2f31aaf161d0', 'message digest'), - - ('c3fcd3d76192e4007dfb496cca67e13b', 'abcdefghijklmnopqrstuvwxyz', - 'a-z'), - - ('d174ab98d277d9f5a5611c2c9f419d9f', - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', - 'A-Z, a-z, 0-9'), - - ('57edf4a22be3c955ac49da2e2107b67a', - '1234567890123456789012345678901234567890123456' - + '7890123456789012345678901234567890', - "'1234567890' * 8"), - - # https://www.cosic.esat.kuleuven.be/nessie/testvectors/hash/md5/Md5-128.unverified.test-vectors - ('57EDF4A22BE3C955AC49DA2E2107B67A', '1234567890' * 8, 'Set 1, vector #7'), - ('7707D6AE4E027C70EEA2A935C2296F21', 'a'*1000000, 'Set 1, vector #8'), -] - - -class Md5IterTest(unittest.TestCase): - - def runTest(self): - message = b("\x00") * 16 - result1 = "4AE71336E44BF9BF79D2752E234818A5".lower() - result2 = "1A83F51285E4D89403D00C46EF8508FE".lower() - - h = MD5.new(message) - message = h.digest() - self.assertEqual(h.hexdigest(), result1) - - for _ in range(99999): - h = MD5.new(message) - message = h.digest() - - self.assertEqual(h.hexdigest(), result2) - - -def get_tests(config={}): - from .common import make_hash_tests - - tests = make_hash_tests(MD5, "MD5", test_data, - digest_size=16, - oid="1.2.840.113549.2.5") - if config.get('slow_tests'): - tests += [ Md5IterTest() ] - 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: diff --git a/Crypto/SelfTest/Hash/test_Poly1305.py b/Crypto/SelfTest/Hash/test_Poly1305.py deleted file mode 100644 index 0bbb6bd..0000000 --- a/Crypto/SelfTest/Hash/test_Poly1305.py +++ /dev/null @@ -1,542 +0,0 @@ -# -# SelfTest/Hash/test_Poly1305.py: Self-test for the Poly1305 module -# -# =================================================================== -# -# Copyright (c) 2018, Helder Eijs -# 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. -# =================================================================== - -"""Self-test suite for Crypto.Hash._Poly1305""" - -import json -import unittest -from binascii import unhexlify, hexlify - -from .common import make_mac_tests -from Crypto.SelfTest.st_common import list_test_cases - -from Crypto.Hash import Poly1305 -from Crypto.Cipher import AES, ChaCha20 - -from Crypto.Util.py3compat import tobytes -from Crypto.Util.strxor import strxor_c - -# This is a list of (r+s keypair, data, result, description, keywords) tuples. -test_data_basic = [ - ( - "85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b", - hexlify(b"Cryptographic Forum Research Group").decode(), - "a8061dc1305136c6c22b8baf0c0127a9", - "RFC7539" - ), - ( - "746869732069732033322d62797465206b657920666f7220506f6c7931333035", - "0000000000000000000000000000000000000000000000000000000000000000", - "49ec78090e481ec6c26b33b91ccc0307", - "https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-00#section-7 A", - ), - ( - "746869732069732033322d62797465206b657920666f7220506f6c7931333035", - "48656c6c6f20776f726c6421", - "a6f745008f81c916a20dcc74eef2b2f0", - "https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-00#section-7 B", - ), - ( - "746869732069732033322d62797465206b657920666f7220506f6c7931333035", - "", - "6b657920666f7220506f6c7931333035", - "Generated with pure Python", - ), - ( - "746869732069732033322d62797465206b657920666f7220506f6c7931333035", - "FF", - "f7e4e0ef4c46d106219da3d1bdaeb3ff", - "Generated with pure Python", - ), - ( - "746869732069732033322d62797465206b657920666f7220506f6c7931333035", - "FF00", - "7471eceeb22988fc936da1d6e838b70e", - "Generated with pure Python", - ), - ( - "746869732069732033322d62797465206b657920666f7220506f6c7931333035", - "AA" * 17, - "32590bc07cb2afaccca3f67f122975fe", - "Generated with pure Python", - ), - ( - "00" * 32, - "00" * 64, - "00" * 16, - "RFC7539 A.3 #1", - ), - ( - "0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e", - hexlify( - b"Any submission t" - b"o the IETF inten" - b"ded by the Contr" - b"ibutor for publi" - b"cation as all or" - b" part of an IETF" - b" Internet-Draft " - b"or RFC and any s" - b"tatement made wi" - b"thin the context" - b" of an IETF acti" - b"vity is consider" - b"ed an \"IETF Cont" - b"ribution\". Such " - b"statements inclu" - b"de oral statemen" - b"ts in IETF sessi" - b"ons, as well as " - b"written and elec" - b"tronic communica" - b"tions made at an" - b"y time or place," - b" which are addre" - b"ssed to").decode(), - "36e5f6b5c5e06070f0efca96227a863e", - "RFC7539 A.3 #2", - ), - ( - "36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000", - hexlify( - b"Any submission t" - b"o the IETF inten" - b"ded by the Contr" - b"ibutor for publi" - b"cation as all or" - b" part of an IETF" - b" Internet-Draft " - b"or RFC and any s" - b"tatement made wi" - b"thin the context" - b" of an IETF acti" - b"vity is consider" - b"ed an \"IETF Cont" - b"ribution\". Such " - b"statements inclu" - b"de oral statemen" - b"ts in IETF sessi" - b"ons, as well as " - b"written and elec" - b"tronic communica" - b"tions made at an" - b"y time or place," - b" which are addre" - b"ssed to").decode(), - "f3477e7cd95417af89a6b8794c310cf0", - "RFC7539 A.3 #3", - ), - ( - "1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0", - "2754776173206272696c6c69672c2061" - "6e642074686520736c6974687920746f" - "7665730a446964206779726520616e64" - "2067696d626c6520696e207468652077" - "6162653a0a416c6c206d696d73792077" - "6572652074686520626f726f676f7665" - "732c0a416e6420746865206d6f6d6520" - "7261746873206f757467726162652e", - "4541669a7eaaee61e708dc7cbcc5eb62", - "RFC7539 A.3 #4", - ), - ( - "02" + "00" * 31, - "FF" * 16, - "03" + "00" * 15, - "RFC7539 A.3 #5", - ), - ( - "02" + "00" * 15 + "FF" * 16, - "02" + "00" * 15, - "03" + "00" * 15, - "RFC7539 A.3 #6", - ), - ( - "01" + "00" * 31, - "FF" * 16 + "F0" + "FF" * 15 + "11" + "00" * 15, - "05" + "00" * 15, - "RFC7539 A.3 #7", - ), - ( - "01" + "00" * 31, - "FF" * 16 + "FB" + "FE" * 15 + "01" * 16, - "00" * 16, - "RFC7539 A.3 #8", - ), - ( - "02" + "00" * 31, - "FD" + "FF" * 15, - "FA" + "FF" * 15, - "RFC7539 A.3 #9", - ), - ( - "01 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00" - "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", - "E3 35 94 D7 50 5E 43 B9 00 00 00 00 00 00 00 00" - "33 94 D7 50 5E 43 79 CD 01 00 00 00 00 00 00 00" - "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" - "01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", - "14 00 00 00 00 00 00 00 55 00 00 00 00 00 00 00", - "RFC7539 A.3 #10", - ), - ( - "01 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00" - "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", - "E3 35 94 D7 50 5E 43 B9 00 00 00 00 00 00 00 00" - "33 94 D7 50 5E 43 79 CD 01 00 00 00 00 00 00 00" - "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", - "13" + "00" * 15, - "RFC7539 A.3 #11", - ), -] - -# This is a list of (key(k+r), data, result, description, keywords) tuples. -test_data_aes = [ - ( - "ec074c835580741701425b623235add6851fc40c3467ac0be05cc20404f3f700", - "f3f6", - "f4c633c3044fc145f84f335cb81953de", - "http://cr.yp.to/mac/poly1305-20050329.pdf", - { 'cipher':AES, 'nonce':unhexlify("fb447350c4e868c52ac3275cf9d4327e") } - ), - ( - "75deaa25c09f208e1dc4ce6b5cad3fbfa0f3080000f46400d0c7e9076c834403", - "", - "dd3fab2251f11ac759f0887129cc2ee7", - "http://cr.yp.to/mac/poly1305-20050329.pdf", - { 'cipher':AES, 'nonce':unhexlify("61ee09218d29b0aaed7e154a2c5509cc") } - ), - ( - "6acb5f61a7176dd320c5c1eb2edcdc7448443d0bb0d21109c89a100b5ce2c208", - "663cea190ffb83d89593f3f476b6bc24" - "d7e679107ea26adb8caf6652d0656136", - "0ee1c16bb73f0f4fd19881753c01cdbe", - "http://cr.yp.to/mac/poly1305-20050329.pdf", - { 'cipher':AES, 'nonce':unhexlify("ae212a55399729595dea458bc621ff0e") } - ), - ( - "e1a5668a4d5b66a5f68cc5424ed5982d12976a08c4426d0ce8a82407c4f48207", - "ab0812724a7f1e342742cbed374d94d1" - "36c6b8795d45b3819830f2c04491faf0" - "990c62e48b8018b2c3e4a0fa3134cb67" - "fa83e158c994d961c4cb21095c1bf9", - "5154ad0d2cb26e01274fc51148491f1b", - "http://cr.yp.to/mac/poly1305-20050329.pdf", - { 'cipher':AES, 'nonce':unhexlify("9ae831e743978d3a23527c7128149e3a") } - ), -] - -test_data_chacha20 = [ - ( - "00" * 32, - "FF" * 15, - "13cc5bbadc36b03a5163928f0bcb65aa", - "RFC7539 A.4 #1", - { 'cipher':ChaCha20, 'nonce':unhexlify("00" * 12) } - ), - ( - "00" * 31 + "01", - "FF" * 15, - "0baf33c1d6df211bdd50a6767e98e00a", - "RFC7539 A.4 #2", - { 'cipher':ChaCha20, 'nonce':unhexlify("00" * 11 + "02") } - ), - ( - "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", - "FF" * 15, - "e8b4c6db226cd8939e65e02eebf834ce", - "RFC7539 A.4 #3", - { 'cipher':ChaCha20, 'nonce':unhexlify("00" * 11 + "02") } - ), - ( - "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", - "f3 33 88 86 00 00 00 00 00 00 4e 91 00 00 00 00" - "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 00 00 00 00 00 00 00" - "0c 00 00 00 00 00 00 00 09 01 00 00 00 00 00 00", - "ee ad 9d 67 89 0c bb 22 39 23 36 fe a1 85 1f 38", - "RFC7539 A.5", - { 'cipher':ChaCha20, 'nonce':unhexlify("000000000102030405060708") } - ), -] - - -class Poly1305Test_AES(unittest.TestCase): - - key = b'\x11' * 32 - - def test_new_positive(self): - - data = b'r' * 100 - - h1 = Poly1305.new(key=self.key, cipher=AES) - self.assertEqual(h1.digest_size, 16) - self.assertEqual(len(h1.nonce), 16) - d1 = h1.update(data).digest() - self.assertEqual(len(d1), 16) - - h2 = Poly1305.new(key=self.key, nonce=h1.nonce, data=data, cipher=AES) - d2 = h2.digest() - self.assertEqual(h1.nonce, h2.nonce) - self.assertEqual(d1, d2) - - def test_new_negative(self): - from Crypto.Cipher import DES3 - - self.assertRaises(ValueError, Poly1305.new, key=self.key[:31], cipher=AES) - self.assertRaises(ValueError, Poly1305.new, key=self.key, cipher=DES3) - self.assertRaises(ValueError, Poly1305.new, key=self.key, nonce=b'1' * 15, cipher=AES) - self.assertRaises(TypeError, Poly1305.new, key=u"2" * 32, cipher=AES) - self.assertRaises(TypeError, Poly1305.new, key=self.key, data=u"2" * 100, cipher=AES) - - def test_update(self): - pieces = [b"\x0A" * 200, b"\x14" * 300] - h1 = Poly1305.new(key=self.key, cipher=AES) - h1.update(pieces[0]).update(pieces[1]) - d1 = h1.digest() - - h2 = Poly1305.new(key=self.key, cipher=AES, nonce=h1.nonce) - h2.update(pieces[0] + pieces[1]) - d2 = h2.digest() - self.assertEqual(d1, d2) - - def test_update_negative(self): - h = Poly1305.new(key=self.key, cipher=AES) - self.assertRaises(TypeError, h.update, u"string") - - def test_digest(self): - h = Poly1305.new(key=self.key, cipher=AES) - digest = h.digest() - - # hexdigest does not change the state - self.assertEqual(h.digest(), digest) - # digest returns a byte string - self.failUnless(isinstance(digest, type(b"digest"))) - - def test_update_after_digest(self): - msg=b"rrrrttt" - - # Normally, update() cannot be done after digest() - h = Poly1305.new(key=self.key, data=msg[:4], cipher=AES) - h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - - def test_hex_digest(self): - mac = Poly1305.new(key=self.key, cipher=AES) - digest = mac.digest() - hexdigest = mac.hexdigest() - - # hexdigest is equivalent to digest - self.assertEqual(hexlify(digest), tobytes(hexdigest)) - # hexdigest does not change the state - self.assertEqual(mac.hexdigest(), hexdigest) - # hexdigest returns a string - self.failUnless(isinstance(hexdigest, type("digest"))) - - def test_verify(self): - h = Poly1305.new(key=self.key, cipher=AES) - mac = h.digest() - h.verify(mac) - wrong_mac = strxor_c(mac, 255) - self.assertRaises(ValueError, h.verify, wrong_mac) - - def test_hexverify(self): - h = Poly1305.new(key=self.key, cipher=AES) - mac = h.hexdigest() - h.hexverify(mac) - self.assertRaises(ValueError, h.hexverify, "4556") - - def test_bytearray(self): - - data = b"\x00\x01\x02" - h0 = Poly1305.new(key=self.key, data=data, cipher=AES) - d_ref = h0.digest() - - # Data and key can be a bytearray (during initialization) - key_ba = bytearray(self.key) - data_ba = bytearray(data) - - h1 = Poly1305.new(key=self.key, data=data, cipher=AES, nonce=h0.nonce) - h2 = Poly1305.new(key=key_ba, data=data_ba, cipher=AES, nonce=h0.nonce) - key_ba[:1] = b'\xFF' - data_ba[:1] = b'\xEE' - - self.assertEqual(h1.digest(), d_ref) - self.assertEqual(h2.digest(), d_ref) - - # Data can be a bytearray (during operation) - data_ba = bytearray(data) - - h1 = Poly1305.new(key=self.key, cipher=AES) - h2 = Poly1305.new(key=self.key, cipher=AES, nonce=h1.nonce) - h1.update(data) - h2.update(data_ba) - data_ba[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) - - def test_memoryview(self): - - data = b"\x00\x01\x02" - - def get_mv_ro(data): - return memoryview(data) - - def get_mv_rw(data): - return memoryview(bytearray(data)) - - for get_mv in (get_mv_ro, get_mv_rw): - - # Data and key can be a memoryview (during initialization) - key_mv = get_mv(self.key) - data_mv = get_mv(data) - - h1 = Poly1305.new(key=self.key, data=data, cipher=AES) - h2 = Poly1305.new(key=key_mv, data=data_mv, cipher=AES, - nonce=h1.nonce) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - key_mv[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) - - # Data can be a memoryview (during operation) - data_mv = get_mv(data) - - h1 = Poly1305.new(key=self.key, cipher=AES) - h2 = Poly1305.new(key=self.key, cipher=AES, nonce=h1.nonce) - h1.update(data) - h2.update(data_mv) - if not data_mv.readonly: - data_mv[:1] = b'\xFF' - - self.assertEqual(h1.digest(), h2.digest()) - - -class Poly1305Test_ChaCha20(unittest.TestCase): - - key = b'\x11' * 32 - - def test_new_positive(self): - data = b'r' * 100 - - h1 = Poly1305.new(key=self.key, cipher=ChaCha20) - self.assertEqual(h1.digest_size, 16) - self.assertEqual(len(h1.nonce), 12) - - h2 = Poly1305.new(key=self.key, cipher=ChaCha20, nonce = b'8' * 8) - self.assertEqual(len(h2.nonce), 8) - self.assertEqual(h2.nonce, b'8' * 8) - - def test_new_negative(self): - - self.assertRaises(ValueError, Poly1305.new, key=self.key, nonce=b'1' * 7, cipher=ChaCha20) - - -# -# make_mac_tests() expect a new() function with signature new(key, data, -# **kwargs), and we need to adapt Poly1305's, as it only uses keywords -# -class Poly1305_New(object): - - @staticmethod - def new(key, *data, **kwds): - _kwds = dict(kwds) - if len(data) == 1: - _kwds['data'] = data[0] - _kwds['key'] = key - return Poly1305.new(**_kwds) - - -class Poly1305_Basic(object): - - @staticmethod - def new(key, *data, **kwds): - from Crypto.Hash.Poly1305 import Poly1305_MAC - - if len(data) == 1: - msg = data[0] - else: - msg = None - - return Poly1305_MAC(key[:16], key[16:], msg) - - -class Poly1305AES_MC(unittest.TestCase): - - def runTest(self): - tag = unhexlify(b"fb447350c4e868c52ac3275cf9d4327e") - - msg = b'' - for msg_len in range(5000 + 1): - key = tag + strxor_c(tag, 0xFF) - nonce = tag[::-1] - if msg_len > 0: - msg = msg + tobytes(tag[0]) - auth = Poly1305.new(key=key, nonce=nonce, cipher=AES, data=msg) - tag = auth.digest() - - # Compare against output of original DJB's poly1305aes-20050218 - self.assertEqual("CDFA436DDD629C7DC20E1128530BAED2", auth.hexdigest().upper()) - - -def get_tests(config={}): - tests = make_mac_tests(Poly1305_Basic, "Poly1305", test_data_basic) - tests += make_mac_tests(Poly1305_New, "Poly1305", test_data_aes) - tests += make_mac_tests(Poly1305_New, "Poly1305", test_data_chacha20) - tests += [ Poly1305AES_MC() ] - tests += list_test_cases(Poly1305Test_AES) - tests += list_test_cases(Poly1305Test_ChaCha20) - return tests - - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/Hash/test_RIPEMD160.py b/Crypto/SelfTest/Hash/test_RIPEMD160.py deleted file mode 100644 index 153c570..0000000 --- a/Crypto/SelfTest/Hash/test_RIPEMD160.py +++ /dev/null @@ -1,71 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Hash/test_RIPEMD160.py: Self-test for the RIPEMD-160 hash function -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -#"""Self-test suite for Crypto.Hash.RIPEMD160""" - -from Crypto.Util.py3compat import * - -# This is a list of (expected_result, input[, description]) tuples. -test_data = [ - # Test vectors downloaded 2008-09-12 from - # http://homes.esat.kuleuven.be/~bosselae/ripemd160.html - ('9c1185a5c5e9fc54612808977ee8f548b2258d31', '', "'' (empty string)"), - ('0bdc9d2d256b3ee9daae347be6f4dc835a467ffe', 'a'), - ('8eb208f7e05d987a9b044a8e98c6b087f15a0bfc', 'abc'), - ('5d0689ef49d2fae572b881b123a85ffa21595f36', 'message digest'), - - ('f71c27109c692c1b56bbdceb5b9d2865b3708dbc', - 'abcdefghijklmnopqrstuvwxyz', - 'a-z'), - - ('12a053384a9c0c88e405a06c27dcf49ada62eb2b', - 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq', - 'abcdbcd...pnopq'), - - ('b0e20b6e3116640286ed3a87a5713079b21f5189', - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', - 'A-Z, a-z, 0-9'), - - ('9b752e45573d4b39f4dbd3323cab82bf63326bfb', - '1234567890' * 8, - "'1234567890' * 8"), - - ('52783243c1697bdbe16d37f97f68f08325dc1528', - 'a' * 10**6, - '"a" * 10**6'), -] - -def get_tests(config={}): - from Crypto.Hash import RIPEMD160 - from .common import make_hash_tests - return make_hash_tests(RIPEMD160, "RIPEMD160", test_data, - digest_size=20, - oid="1.3.36.3.2.1") - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') - -# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/Crypto/SelfTest/Hash/test_SHA1.py b/Crypto/SelfTest/Hash/test_SHA1.py deleted file mode 100644 index a883a44..0000000 --- a/Crypto/SelfTest/Hash/test_SHA1.py +++ /dev/null @@ -1,84 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Hash/SHA1.py: Self-test for the SHA-1 hash function -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-test suite for Crypto.Hash.SHA""" - -from binascii import hexlify - -from Crypto.SelfTest.loader import load_test_vectors - -# Test vectors from various sources -# This is a list of (expected_result, input[, description]) tuples. -test_data_various = [ - # FIPS PUB 180-2, A.1 - "One-Block Message" - ('a9993e364706816aba3e25717850c26c9cd0d89d', 'abc'), - - # FIPS PUB 180-2, A.2 - "Multi-Block Message" - ('84983e441c3bd26ebaae4aa1f95129e5e54670f1', - 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'), - - # FIPS PUB 180-2, A.3 - "Long Message" -# ('34aa973cd4c4daa4f61eeb2bdbad27316534016f', -# 'a' * 10**6, -# '"a" * 10**6'), - - # RFC 3174: Section 7.3, "TEST4" (multiple of 512 bits) - ('dea356a2cddd90c7a7ecedc5ebb563934f460452', - '01234567' * 80, - '"01234567" * 80'), -] - -def get_tests(config={}): - from Crypto.Hash import SHA1 - from .common import make_hash_tests - - tests = [] - - test_vectors = load_test_vectors(("Hash", "SHA1"), - "SHA1ShortMsg.rsp", - "KAT SHA-1", - { "len" : lambda x: int(x) } ) or [] - - test_data = test_data_various[:] - for tv in test_vectors: - try: - if tv.startswith('['): - continue - except AttributeError: - pass - if tv.len == 0: - tv.msg = b"" - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - - tests = make_hash_tests(SHA1, "SHA1", test_data, - digest_size=20, - oid="1.3.14.3.2.26") - 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: diff --git a/Crypto/SelfTest/Hash/test_SHA224.py b/Crypto/SelfTest/Hash/test_SHA224.py deleted file mode 100644 index cf81ad9..0000000 --- a/Crypto/SelfTest/Hash/test_SHA224.py +++ /dev/null @@ -1,63 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Hash/test_SHA224.py: Self-test for the SHA-224 hash function -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-test suite for Crypto.Hash.SHA224""" - -# Test vectors from various sources -# This is a list of (expected_result, input[, description]) tuples. -test_data = [ - - # RFC 3874: Section 3.1, "Test Vector #1 - ('23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7', 'abc'), - - # RFC 3874: Section 3.2, "Test Vector #2 - ('75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525', 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'), - - # RFC 3874: Section 3.3, "Test Vector #3 - ('20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67', 'a' * 10**6, "'a' * 10**6"), - - # Examples from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm - ('d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f', ''), - - ('49b08defa65e644cbf8a2dd9270bdededabc741997d1dadd42026d7b', - 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'), - - ('58911e7fccf2971a7d07f93162d8bd13568e71aa8fc86fc1fe9043d1', - 'Frank jagt im komplett verwahrlosten Taxi quer durch Bayern'), - -] - -def get_tests(config={}): - from Crypto.Hash import SHA224 - from .common import make_hash_tests - return make_hash_tests(SHA224, "SHA224", test_data, - digest_size=28, - oid='2.16.840.1.101.3.4.2.4') - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') - -# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/Crypto/SelfTest/Hash/test_SHA256.py b/Crypto/SelfTest/Hash/test_SHA256.py deleted file mode 100644 index bb99326..0000000 --- a/Crypto/SelfTest/Hash/test_SHA256.py +++ /dev/null @@ -1,94 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Hash/test_SHA256.py: Self-test for the SHA-256 hash function -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-test suite for Crypto.Hash.SHA256""" - -import unittest -from Crypto.Util.py3compat import * - -class LargeSHA256Test(unittest.TestCase): - def runTest(self): - """SHA256: 512/520 MiB test""" - from Crypto.Hash import SHA256 - zeros = bchr(0x00) * (1024*1024) - - h = SHA256.new(zeros) - for i in range(511): - h.update(zeros) - - # This test vector is from PyCrypto's old testdata.py file. - self.assertEqual('9acca8e8c22201155389f65abbf6bc9723edc7384ead80503839f49dcc56d767', h.hexdigest()) # 512 MiB - - for i in range(8): - h.update(zeros) - - # This test vector is from PyCrypto's old testdata.py file. - self.assertEqual('abf51ad954b246009dfe5a50ecd582fd5b8f1b8b27f30393853c3ef721e7fa6e', h.hexdigest()) # 520 MiB - -def get_tests(config={}): - # Test vectors from FIPS PUB 180-2 - # This is a list of (expected_result, input[, description]) tuples. - test_data = [ - # FIPS PUB 180-2, B.1 - "One-Block Message" - ('ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad', - 'abc'), - - # FIPS PUB 180-2, B.2 - "Multi-Block Message" - ('248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1', - 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'), - - # FIPS PUB 180-2, B.3 - "Long Message" - ('cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0', - 'a' * 10**6, - '"a" * 10**6'), - - # Test for an old PyCrypto bug. - ('f7fd017a3c721ce7ff03f3552c0813adcc48b7f33f07e5e2ba71e23ea393d103', - 'This message is precisely 55 bytes long, to test a bug.', - 'Length = 55 (mod 64)'), - - # Example from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm - ('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', ''), - - ('d32b568cd1b96d459e7291ebf4b25d007f275c9f13149beeb782fac0716613f8', - 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'), - ] - - from Crypto.Hash import SHA256 - from .common import make_hash_tests - tests = make_hash_tests(SHA256, "SHA256", test_data, - digest_size=32, - oid="2.16.840.1.101.3.4.2.1") - - if config.get('slow_tests'): - tests += [LargeSHA256Test()] - - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') - -# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/Crypto/SelfTest/Hash/test_SHA384.py b/Crypto/SelfTest/Hash/test_SHA384.py deleted file mode 100644 index c682eb4..0000000 --- a/Crypto/SelfTest/Hash/test_SHA384.py +++ /dev/null @@ -1,61 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Hash/test_SHA.py: Self-test for the SHA-384 hash function -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-test suite for Crypto.Hash.SHA384""" - -# Test vectors from various sources -# This is a list of (expected_result, input[, description]) tuples. -test_data = [ - - # RFC 4634: Section Page 8.4, "Test 1" - ('cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7', 'abc'), - - # RFC 4634: Section Page 8.4, "Test 2.2" - ('09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039', 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu'), - - # RFC 4634: Section Page 8.4, "Test 3" - ('9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985', 'a' * 10**6, "'a' * 10**6"), - - # Taken from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm - ('38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b', ''), - - # Example from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm - ('71e8383a4cea32d6fd6877495db2ee353542f46fa44bc23100bca48f3366b84e809f0708e81041f427c6d5219a286677', - 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'), - -] - -def get_tests(config={}): - from Crypto.Hash import SHA384 - from .common import make_hash_tests - return make_hash_tests(SHA384, "SHA384", test_data, - digest_size=48, - oid='2.16.840.1.101.3.4.2.2') - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') - -# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/Crypto/SelfTest/Hash/test_SHA3_224.py b/Crypto/SelfTest/Hash/test_SHA3_224.py deleted file mode 100644 index 6dbf661..0000000 --- a/Crypto/SelfTest/Hash/test_SHA3_224.py +++ /dev/null @@ -1,79 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Hash/test_SHA3_224.py: Self-test for the SHA-3/224 hash function -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-test suite for Crypto.Hash.SHA3_224""" - -import unittest -from binascii import hexlify - -from Crypto.SelfTest.loader import load_test_vectors -from Crypto.SelfTest.st_common import list_test_cases -from Crypto.Hash import SHA3_224 as SHA3 -from Crypto.Util.py3compat import b - - -class APITest(unittest.TestCase): - - def test_update_after_digest(self): - msg=b("rrrrttt") - - # Normally, update() cannot be done after digest() - h = SHA3.new(data=msg[:4]) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - dig2 = SHA3.new(data=msg).digest() - - # With the proper flag, it is allowed - h = SHA3.new(data=msg[:4], update_after_digest=True) - self.assertEquals(h.digest(), dig1) - # ... and the subsequent digest applies to the entire message - # up to that point - h.update(msg[4:]) - self.assertEquals(h.digest(), dig2) - - -def get_tests(config={}): - from .common import make_hash_tests - - tests = [] - - test_vectors = load_test_vectors(("Hash", "SHA3"), - "ShortMsgKAT_SHA3-224.txt", - "KAT SHA-3 224", - { "len" : lambda x: int(x) } ) or [] - - test_data = [] - for tv in test_vectors: - if tv.len == 0: - tv.msg = b("") - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - - tests += make_hash_tests(SHA3, "SHA3_224", test_data, - digest_size=SHA3.digest_size, - oid="2.16.840.1.101.3.4.2.7") - tests += list_test_cases(APITest) - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/Hash/test_SHA3_256.py b/Crypto/SelfTest/Hash/test_SHA3_256.py deleted file mode 100644 index b017852..0000000 --- a/Crypto/SelfTest/Hash/test_SHA3_256.py +++ /dev/null @@ -1,80 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Hash/test_SHA3_256.py: Self-test for the SHA-3/256 hash function -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-test suite for Crypto.Hash.SHA3_256""" - -import unittest -from binascii import hexlify - -from Crypto.SelfTest.loader import load_test_vectors -from Crypto.SelfTest.st_common import list_test_cases -from Crypto.Hash import SHA3_256 as SHA3 -from Crypto.Util.py3compat import b - - -class APITest(unittest.TestCase): - - def test_update_after_digest(self): - msg=b("rrrrttt") - - # Normally, update() cannot be done after digest() - h = SHA3.new(data=msg[:4]) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - dig2 = SHA3.new(data=msg).digest() - - # With the proper flag, it is allowed - h = SHA3.new(data=msg[:4], update_after_digest=True) - self.assertEquals(h.digest(), dig1) - # ... and the subsequent digest applies to the entire message - # up to that point - h.update(msg[4:]) - self.assertEquals(h.digest(), dig2) - - -def get_tests(config={}): - from .common import make_hash_tests - - tests = [] - - test_vectors = load_test_vectors(("Hash", "SHA3"), - "ShortMsgKAT_SHA3-256.txt", - "KAT SHA-3 256", - { "len" : lambda x: int(x) } ) or [] - - test_data = [] - for tv in test_vectors: - if tv.len == 0: - tv.msg = b("") - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - - - tests += make_hash_tests(SHA3, "SHA3_256", test_data, - digest_size=SHA3.digest_size, - oid="2.16.840.1.101.3.4.2.8") - tests += list_test_cases(APITest) - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/Hash/test_SHA3_384.py b/Crypto/SelfTest/Hash/test_SHA3_384.py deleted file mode 100644 index 88d8c50..0000000 --- a/Crypto/SelfTest/Hash/test_SHA3_384.py +++ /dev/null @@ -1,79 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Hash/test_SHA3_384.py: Self-test for the SHA-3/384 hash function -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-test suite for Crypto.Hash.SHA3_384""" - -import unittest -from binascii import hexlify - -from Crypto.SelfTest.loader import load_test_vectors -from Crypto.SelfTest.st_common import list_test_cases -from Crypto.Hash import SHA3_384 as SHA3 -from Crypto.Util.py3compat import b - - -class APITest(unittest.TestCase): - - def test_update_after_digest(self): - msg=b("rrrrttt") - - # Normally, update() cannot be done after digest() - h = SHA3.new(data=msg[:4]) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - dig2 = SHA3.new(data=msg).digest() - - # With the proper flag, it is allowed - h = SHA3.new(data=msg[:4], update_after_digest=True) - self.assertEquals(h.digest(), dig1) - # ... and the subsequent digest applies to the entire message - # up to that point - h.update(msg[4:]) - self.assertEquals(h.digest(), dig2) - - -def get_tests(config={}): - from .common import make_hash_tests - - tests = [] - - test_vectors = load_test_vectors(("Hash", "SHA3"), - "ShortMsgKAT_SHA3-384.txt", - "KAT SHA-3 384", - { "len" : lambda x: int(x) } ) or [] - - test_data = [] - for tv in test_vectors: - if tv.len == 0: - tv.msg = b("") - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - - tests += make_hash_tests(SHA3, "SHA3_384", test_data, - digest_size=SHA3.digest_size, - oid="2.16.840.1.101.3.4.2.9") - tests += list_test_cases(APITest) - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/Hash/test_SHA3_512.py b/Crypto/SelfTest/Hash/test_SHA3_512.py deleted file mode 100644 index d012003..0000000 --- a/Crypto/SelfTest/Hash/test_SHA3_512.py +++ /dev/null @@ -1,79 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Hash/test_SHA3_512.py: Self-test for the SHA-3/512 hash function -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-test suite for Crypto.Hash.SHA3_512""" - -import unittest -from binascii import hexlify - -from Crypto.SelfTest.loader import load_test_vectors -from Crypto.SelfTest.st_common import list_test_cases -from Crypto.Hash import SHA3_512 as SHA3 -from Crypto.Util.py3compat import b - - -class APITest(unittest.TestCase): - - def test_update_after_digest(self): - msg=b("rrrrttt") - - # Normally, update() cannot be done after digest() - h = SHA3.new(data=msg[:4]) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - dig2 = SHA3.new(data=msg).digest() - - # With the proper flag, it is allowed - h = SHA3.new(data=msg[:4], update_after_digest=True) - self.assertEquals(h.digest(), dig1) - # ... and the subsequent digest applies to the entire message - # up to that point - h.update(msg[4:]) - self.assertEquals(h.digest(), dig2) - - -def get_tests(config={}): - from .common import make_hash_tests - - tests = [] - - test_vectors = load_test_vectors(("Hash", "SHA3"), - "ShortMsgKAT_SHA3-512.txt", - "KAT SHA-3 512", - { "len" : lambda x: int(x) } ) or [] - - test_data = [] - for tv in test_vectors: - if tv.len == 0: - tv.msg = b("") - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - - tests += make_hash_tests(SHA3, "SHA3_512", test_data, - digest_size=SHA3.digest_size, - oid="2.16.840.1.101.3.4.2.10") - tests += list_test_cases(APITest) - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/Hash/test_SHA512.py b/Crypto/SelfTest/Hash/test_SHA512.py deleted file mode 100644 index 20961ac..0000000 --- a/Crypto/SelfTest/Hash/test_SHA512.py +++ /dev/null @@ -1,140 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Hash/test_SHA512.py: Self-test for the SHA-512 hash function -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-test suite for Crypto.Hash.SHA512""" - -from binascii import hexlify - -from Crypto.Hash import SHA512 -from .common import make_hash_tests -from Crypto.SelfTest.loader import load_test_vectors - -# Test vectors from various sources -# This is a list of (expected_result, input[, description]) tuples. -test_data_512_other = [ - - # RFC 4634: Section Page 8.4, "Test 1" - ('ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f', 'abc'), - - # RFC 4634: Section Page 8.4, "Test 2.1" - ('8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909', 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu'), - - # RFC 4634: Section Page 8.4, "Test 3" - ('e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b', 'a' * 10**6, "'a' * 10**6"), - - # Taken from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm - ('cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e', ''), - - ('af9ed2de700433b803240a552b41b5a472a6ef3fe1431a722b2063c75e9f07451f67a28e37d09cde769424c96aea6f8971389db9e1993d6c565c3c71b855723c', 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'), -] - - -def get_tests_SHA512(): - - test_vectors = load_test_vectors(("Hash", "SHA2"), - "SHA512ShortMsg.rsp", - "KAT SHA-512", - {"len": lambda x: int(x)}) or [] - - test_data = test_data_512_other[:] - for tv in test_vectors: - try: - if tv.startswith('['): - continue - except AttributeError: - pass - if tv.len == 0: - tv.msg = b"" - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - - tests = make_hash_tests(SHA512, "SHA512", test_data, - digest_size=64, - oid="2.16.840.1.101.3.4.2.3") - return tests - - -def get_tests_SHA512_224(): - - test_vectors = load_test_vectors(("Hash", "SHA2"), - "SHA512_224ShortMsg.rsp", - "KAT SHA-512/224", - {"len": lambda x: int(x)}) or [] - - test_data = [] - for tv in test_vectors: - try: - if tv.startswith('['): - continue - except AttributeError: - pass - if tv.len == 0: - tv.msg = b"" - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - - tests = make_hash_tests(SHA512, "SHA512/224", test_data, - digest_size=28, - oid="2.16.840.1.101.3.4.2.5", - extra_params={ "truncate" : "224" }) - return tests - - -def get_tests_SHA512_256(): - - test_vectors = load_test_vectors(("Hash", "SHA2"), - "SHA512_256ShortMsg.rsp", - "KAT SHA-512/256", - {"len": lambda x: int(x)}) or [] - - test_data = [] - for tv in test_vectors: - try: - if tv.startswith('['): - continue - except AttributeError: - pass - if tv.len == 0: - tv.msg = b"" - test_data.append((hexlify(tv.md), tv.msg, tv.desc)) - - tests = make_hash_tests(SHA512, "SHA512/256", test_data, - digest_size=32, - oid="2.16.840.1.101.3.4.2.6", - extra_params={ "truncate" : "256" }) - return tests - - -def get_tests(config={}): - - tests = [] - tests += get_tests_SHA512() - tests += get_tests_SHA512_224() - tests += get_tests_SHA512_256() - 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: diff --git a/Crypto/SelfTest/Hash/test_SHAKE.py b/Crypto/SelfTest/Hash/test_SHAKE.py deleted file mode 100644 index 77a07e8..0000000 --- a/Crypto/SelfTest/Hash/test_SHAKE.py +++ /dev/null @@ -1,143 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2015, Legrandin -# 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. -# =================================================================== - -"""Self-test suite for Crypto.Hash.SHAKE128 and SHAKE256""" - -import unittest -from binascii import hexlify, unhexlify - -from Crypto.SelfTest.loader import load_test_vectors -from Crypto.SelfTest.st_common import list_test_cases - -from Crypto.Hash import SHAKE128, SHAKE256 -from Crypto.Util.py3compat import b, bchr, bord, tobytes - -class SHAKETest(unittest.TestCase): - - def test_new_positive(self): - - xof1 = self.shake.new() - xof2 = self.shake.new(data=b("90")) - xof3 = self.shake.new().update(b("90")) - - self.assertNotEqual(xof1.read(10), xof2.read(10)) - xof3.read(10) - self.assertEqual(xof2.read(10), xof3.read(10)) - - def test_update(self): - pieces = [bchr(10) * 200, bchr(20) * 300] - h = self.shake.new() - h.update(pieces[0]).update(pieces[1]) - digest = h.read(10) - h = self.shake.new() - h.update(pieces[0] + pieces[1]) - self.assertEqual(h.read(10), digest) - - def test_update_negative(self): - h = self.shake.new() - self.assertRaises(TypeError, h.update, u"string") - - def test_digest(self): - h = self.shake.new() - digest = h.read(90) - - # read returns a byte string of the right length - self.failUnless(isinstance(digest, type(b("digest")))) - self.assertEqual(len(digest), 90) - - def test_update_after_read(self): - mac = self.shake.new() - mac.update(b("rrrr")) - mac.read(90) - self.assertRaises(TypeError, mac.update, b("ttt")) - - -class SHAKE128Test(SHAKETest): - shake = SHAKE128 - - -class SHAKE256Test(SHAKETest): - shake = SHAKE256 - - -class SHAKEVectors(unittest.TestCase): - pass - - -test_vectors_128 = load_test_vectors(("Hash", "SHA3"), - "ShortMsgKAT_SHAKE128.txt", - "Short Messages KAT SHAKE128", - { "len" : lambda x: int(x) } ) or [] - -for idx, tv in enumerate(test_vectors_128): - if tv.len == 0: - data = b("") - else: - data = tobytes(tv.msg) - - def new_test(self, data=data, result=tv.md): - hobj = SHAKE128.new(data=data) - digest = hobj.read(len(result)) - self.assertEqual(digest, result) - - setattr(SHAKEVectors, "test_128_%d" % idx, new_test) - - -test_vectors_256 = load_test_vectors(("Hash", "SHA3"), - "ShortMsgKAT_SHAKE256.txt", - "Short Messages KAT SHAKE256", - { "len" : lambda x: int(x) } ) or [] - -for idx, tv in enumerate(test_vectors_256): - if tv.len == 0: - data = b("") - else: - data = tobytes(tv.msg) - - def new_test(self, data=data, result=tv.md): - hobj = SHAKE256.new(data=data) - digest = hobj.read(len(result)) - self.assertEqual(digest, result) - - setattr(SHAKEVectors, "test_256_%d" % idx, new_test) - - -def get_tests(config={}): - tests = [] - tests += list_test_cases(SHAKE128Test) - tests += list_test_cases(SHAKE256Test) - tests += list_test_cases(SHAKEVectors) - return tests - - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/Hash/test_keccak.py b/Crypto/SelfTest/Hash/test_keccak.py deleted file mode 100644 index 92e2453..0000000 --- a/Crypto/SelfTest/Hash/test_keccak.py +++ /dev/null @@ -1,250 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2015, Legrandin -# 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. -# =================================================================== - -"""Self-test suite for Crypto.Hash.keccak""" - -import unittest -from binascii import hexlify, unhexlify - -from Crypto.SelfTest.loader import load_test_vectors -from Crypto.SelfTest.st_common import list_test_cases - -from Crypto.Hash import keccak -from Crypto.Util.py3compat import b, tobytes, bchr - -class KeccakTest(unittest.TestCase): - - def test_new_positive(self): - - for digest_bits in (224, 256, 384, 512): - hobj = keccak.new(digest_bits=digest_bits) - self.assertEqual(hobj.digest_size, digest_bits // 8) - - hobj2 = hobj.new() - self.assertEqual(hobj2.digest_size, digest_bits // 8) - - for digest_bytes in (28, 32, 48, 64): - hobj = keccak.new(digest_bytes=digest_bytes) - self.assertEqual(hobj.digest_size, digest_bytes) - - hobj2 = hobj.new() - self.assertEqual(hobj2.digest_size, digest_bytes) - - def test_new_positive2(self): - - digest1 = keccak.new(data=b("\x90"), digest_bytes=64).digest() - digest2 = keccak.new(digest_bytes=64).update(b("\x90")).digest() - self.assertEqual(digest1, digest2) - - def test_new_negative(self): - - # keccak.new needs digest size - self.assertRaises(TypeError, keccak.new) - - h = keccak.new(digest_bits=512) - - # Either bits or bytes can be specified - self.assertRaises(TypeError, keccak.new, - digest_bytes=64, - digest_bits=512) - - # Range - self.assertRaises(ValueError, keccak.new, digest_bytes=0) - self.assertRaises(ValueError, keccak.new, digest_bytes=1) - self.assertRaises(ValueError, keccak.new, digest_bytes=65) - self.assertRaises(ValueError, keccak.new, digest_bits=0) - self.assertRaises(ValueError, keccak.new, digest_bits=1) - self.assertRaises(ValueError, keccak.new, digest_bits=513) - - def test_update(self): - pieces = [bchr(10) * 200, bchr(20) * 300] - h = keccak.new(digest_bytes=64) - h.update(pieces[0]).update(pieces[1]) - digest = h.digest() - h = keccak.new(digest_bytes=64) - h.update(pieces[0] + pieces[1]) - self.assertEqual(h.digest(), digest) - - def test_update_negative(self): - h = keccak.new(digest_bytes=64) - self.assertRaises(TypeError, h.update, u"string") - - def test_digest(self): - h = keccak.new(digest_bytes=64) - digest = h.digest() - - # hexdigest does not change the state - self.assertEqual(h.digest(), digest) - # digest returns a byte string - self.failUnless(isinstance(digest, type(b("digest")))) - - def test_hex_digest(self): - mac = keccak.new(digest_bits=512) - digest = mac.digest() - hexdigest = mac.hexdigest() - - # hexdigest is equivalent to digest - self.assertEqual(hexlify(digest), tobytes(hexdigest)) - # hexdigest does not change the state - self.assertEqual(mac.hexdigest(), hexdigest) - # hexdigest returns a string - self.failUnless(isinstance(hexdigest, type("digest"))) - - def test_update_after_digest(self): - msg=b("rrrrttt") - - # Normally, update() cannot be done after digest() - h = keccak.new(digest_bits=512, data=msg[:4]) - dig1 = h.digest() - self.assertRaises(TypeError, h.update, msg[4:]) - dig2 = keccak.new(digest_bits=512, data=msg).digest() - - # With the proper flag, it is allowed - h = keccak.new(digest_bits=512, data=msg[:4], update_after_digest=True) - self.assertEquals(h.digest(), dig1) - # ... and the subsequent digest applies to the entire message - # up to that point - h.update(msg[4:]) - self.assertEquals(h.digest(), dig2) - - -class KeccakVectors(unittest.TestCase): - pass - - # TODO: add ExtremelyLong tests - - -test_vectors_224 = load_test_vectors(("Hash", "keccak"), - "ShortMsgKAT_224.txt", - "Short Messages KAT 224", - {"len": lambda x: int(x)}) or [] - -test_vectors_224 += load_test_vectors(("Hash", "keccak"), - "LongMsgKAT_224.txt", - "Long Messages KAT 224", - {"len": lambda x: int(x)}) or [] - -for idx, tv in enumerate(test_vectors_224): - if tv.len == 0: - data = b("") - else: - data = tobytes(tv.msg) - - def new_test(self, data=data, result=tv.md): - hobj = keccak.new(digest_bits=224, data=data) - self.assertEqual(hobj.digest(), result) - - setattr(KeccakVectors, "test_224_%d" % idx, new_test) - -# --- - -test_vectors_256 = load_test_vectors(("Hash", "keccak"), - "ShortMsgKAT_256.txt", - "Short Messages KAT 256", - { "len" : lambda x: int(x) } ) or [] - -test_vectors_256 += load_test_vectors(("Hash", "keccak"), - "LongMsgKAT_256.txt", - "Long Messages KAT 256", - { "len" : lambda x: int(x) } ) or [] - -for idx, tv in enumerate(test_vectors_256): - if tv.len == 0: - data = b("") - else: - data = tobytes(tv.msg) - - def new_test(self, data=data, result=tv.md): - hobj = keccak.new(digest_bits=256, data=data) - self.assertEqual(hobj.digest(), result) - - setattr(KeccakVectors, "test_256_%d" % idx, new_test) - - -# --- - -test_vectors_384 = load_test_vectors(("Hash", "keccak"), - "ShortMsgKAT_384.txt", - "Short Messages KAT 384", - {"len": lambda x: int(x)}) or [] - -test_vectors_384 += load_test_vectors(("Hash", "keccak"), - "LongMsgKAT_384.txt", - "Long Messages KAT 384", - {"len": lambda x: int(x)}) or [] - -for idx, tv in enumerate(test_vectors_384): - if tv.len == 0: - data = b("") - else: - data = tobytes(tv.msg) - - def new_test(self, data=data, result=tv.md): - hobj = keccak.new(digest_bits=384, data=data) - self.assertEqual(hobj.digest(), result) - - setattr(KeccakVectors, "test_384_%d" % idx, new_test) - -# --- - -test_vectors_512 = load_test_vectors(("Hash", "keccak"), - "ShortMsgKAT_512.txt", - "Short Messages KAT 512", - {"len": lambda x: int(x)}) or [] - -test_vectors_512 += load_test_vectors(("Hash", "keccak"), - "LongMsgKAT_512.txt", - "Long Messages KAT 512", - {"len": lambda x: int(x)}) or [] - -for idx, tv in enumerate(test_vectors_512): - if tv.len == 0: - data = b("") - else: - data = tobytes(tv.msg) - - def new_test(self, data=data, result=tv.md): - hobj = keccak.new(digest_bits=512, data=data) - self.assertEqual(hobj.digest(), result) - - setattr(KeccakVectors, "test_512_%d" % idx, new_test) - - -def get_tests(config={}): - tests = [] - tests += list_test_cases(KeccakTest) - tests += list_test_cases(KeccakVectors) - return tests - - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/IO/__init__.py b/Crypto/SelfTest/IO/__init__.py deleted file mode 100644 index c04a2a7..0000000 --- a/Crypto/SelfTest/IO/__init__.py +++ /dev/null @@ -1,47 +0,0 @@ -# -# SelfTest/IO/__init__.py: Self-test for input/output module -# -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -"""Self-test for I/O""" - -def get_tests(config={}): - tests = [] - from Crypto.SelfTest.IO import test_PKCS8; tests += test_PKCS8.get_tests(config=config) - from Crypto.SelfTest.IO import test_PBES; tests += test_PBES.get_tests(config=config) - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') - - diff --git a/Crypto/SelfTest/IO/__pycache__/__init__.cpython-36.pyc b/Crypto/SelfTest/IO/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index af2a366..0000000 Binary files a/Crypto/SelfTest/IO/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/IO/__pycache__/test_PBES.cpython-36.pyc b/Crypto/SelfTest/IO/__pycache__/test_PBES.cpython-36.pyc deleted file mode 100644 index 0db76c7..0000000 Binary files a/Crypto/SelfTest/IO/__pycache__/test_PBES.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/IO/__pycache__/test_PKCS8.cpython-36.pyc b/Crypto/SelfTest/IO/__pycache__/test_PKCS8.cpython-36.pyc deleted file mode 100644 index 9f594fb..0000000 Binary files a/Crypto/SelfTest/IO/__pycache__/test_PKCS8.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/IO/test_PBES.py b/Crypto/SelfTest/IO/test_PBES.py deleted file mode 100644 index b2a4f94..0000000 --- a/Crypto/SelfTest/IO/test_PBES.py +++ /dev/null @@ -1,93 +0,0 @@ -# -# SelfTest/IO/test_PBES.py: Self-test for the _PBES module -# -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -"""Self-tests for Crypto.IO._PBES module""" - -import unittest -from Crypto.Util.py3compat import * - -from Crypto.IO._PBES import PBES2 - - -class TestPBES2(unittest.TestCase): - - def setUp(self): - self.ref = b("Test data") - self.passphrase = b("Passphrase") - - def test1(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - def test2(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'PBKDF2WithHMAC-SHA1AndAES128-CBC') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - def test3(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'PBKDF2WithHMAC-SHA1AndAES192-CBC') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - def test4(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'scryptAndAES128-CBC') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - def test5(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'scryptAndAES192-CBC') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - def test6(self): - ct = PBES2.encrypt(self.ref, self.passphrase, - 'scryptAndAES256-CBC') - pt = PBES2.decrypt(ct, self.passphrase) - self.assertEqual(self.ref, pt) - - -def get_tests(config={}): - from Crypto.SelfTest.st_common import list_test_cases - listTests = [] - listTests += list_test_cases(TestPBES2) - return listTests - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/IO/test_PKCS8.py b/Crypto/SelfTest/IO/test_PKCS8.py deleted file mode 100644 index 49f4b8a..0000000 --- a/Crypto/SelfTest/IO/test_PKCS8.py +++ /dev/null @@ -1,423 +0,0 @@ -# -# SelfTest/IO/test_PKCS8.py: Self-test for the PKCS8 module -# -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -"""Self-tests for Crypto.IO.PKCS8 module""" - -import unittest -from binascii import unhexlify - -from Crypto.Util.py3compat import * -from Crypto.IO import PKCS8 - -oid_key = '1.2.840.113549.1.1.1' - -# Original RSA key (in DER format) -# hexdump -v -e '32/1 "%02x" "\n"' key.der -clear_key=""" -308201ab020100025a00b94a7f7075ab9e79e8196f47be707781e80dd965cf16 -0c951a870b71783b6aaabbd550c0e65e5a3dfe15b8620009f6d7e5efec42a3f0 -6fe20faeebb0c356e79cdec6db4dd427e82d8ae4a5b90996227b8ba54ccfc4d2 -5c08050203010001025a00afa09c70d528299b7552fe766b5d20f9a221d66938 -c3b68371d48515359863ff96f0978d700e08cd6fd3d8a3f97066fc2e0d5f78eb -3a50b8e17ba297b24d1b8e9cdfd18d608668198d724ad15863ef0329195dee89 -3f039395022d0ebe0518df702a8b25954301ec60a97efdcec8eaa4f2e76ca7e8 -8dfbc3f7e0bb83f9a0e8dc47c0f8c746e9df6b022d0c9195de13f09b7be1fdd7 -1f56ae7d973e08bd9fd2c3dfd8936bb05be9cc67bd32d663c7f00d70932a0be3 -c24f022d0ac334eb6cabf1933633db007b763227b0d9971a9ea36aca8b669ec9 -4fcf16352f6b3dcae28e4bd6137db4ddd3022d0400a09f15ee7b351a2481cb03 -09920905c236d09c87afd3022f3afc2a19e3b746672b635238956ee7e6dd62d5 -022d0cd88ed14fcfbda5bbf0257f700147137bbab9c797af7df866704b889aa3 -7e2e93df3ff1a0fd3490111dcdbc4c -""" - -# Same key as above, wrapped in PKCS#8 but w/o password -# -# openssl pkcs8 -topk8 -inform DER -nocrypt -in key.der -outform DER -out keyp8.der -# hexdump -v -e '32/1 "%02x" "\n"' keyp8.der -wrapped_clear_key=""" -308201c5020100300d06092a864886f70d0101010500048201af308201ab0201 -00025a00b94a7f7075ab9e79e8196f47be707781e80dd965cf160c951a870b71 -783b6aaabbd550c0e65e5a3dfe15b8620009f6d7e5efec42a3f06fe20faeebb0 -c356e79cdec6db4dd427e82d8ae4a5b90996227b8ba54ccfc4d25c0805020301 -0001025a00afa09c70d528299b7552fe766b5d20f9a221d66938c3b68371d485 -15359863ff96f0978d700e08cd6fd3d8a3f97066fc2e0d5f78eb3a50b8e17ba2 -97b24d1b8e9cdfd18d608668198d724ad15863ef0329195dee893f039395022d -0ebe0518df702a8b25954301ec60a97efdcec8eaa4f2e76ca7e88dfbc3f7e0bb -83f9a0e8dc47c0f8c746e9df6b022d0c9195de13f09b7be1fdd71f56ae7d973e -08bd9fd2c3dfd8936bb05be9cc67bd32d663c7f00d70932a0be3c24f022d0ac3 -34eb6cabf1933633db007b763227b0d9971a9ea36aca8b669ec94fcf16352f6b -3dcae28e4bd6137db4ddd3022d0400a09f15ee7b351a2481cb0309920905c236 -d09c87afd3022f3afc2a19e3b746672b635238956ee7e6dd62d5022d0cd88ed1 -4fcfbda5bbf0257f700147137bbab9c797af7df866704b889aa37e2e93df3ff1 -a0fd3490111dcdbc4c -""" - -### -# -# The key above will now be encrypted with different algorithms. -# The password is always 'TestTest'. -# -# Each item in the wrapped_enc_keys list contains: -# * wrap algorithm -# * iteration count -# * Salt -# * IV -# * Expected result -### -wrapped_enc_keys = [] - -# -# openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der -outform DER -out keyenc.der -v2 des3 -# hexdump -v -e '32/1 "%02x" "\n"' keyenc.der -# -wrapped_enc_keys.append(( -'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC', -2048, -"47EA7227D8B22E2F", # IV -"E3F7A838AB911A4D", # Salt -""" -30820216304006092a864886f70d01050d3033301b06092a864886f70d01050c -300e0408e3f7a838ab911a4d02020800301406082a864886f70d0307040847ea -7227d8b22e2f048201d0ea388b374d2d0e4ceb7a5139f850fdff274884a6e6c0 -64326e09d00dbba9018834edb5a51a6ae3d1806e6e91eebf33788ce71fee0637 -a2ebf58859dd32afc644110c390274a6128b50c39b8d907823810ec471bada86 -6f5b75d8ea04ad310fad2e73621696db8e426cd511ee93ec1714a1a7db45e036 -4bf20d178d1f16bbb250b32c2d200093169d588de65f7d99aad9ddd0104b44f1 -326962e1520dfac3c2a800e8a14f678dff2b3d0bb23f69da635bf2a643ac934e -219a447d2f4460b67149e860e54f365da130763deefa649c72b0dcd48966a2d3 -4a477444782e3e66df5a582b07bbb19778a79bd355074ce331f4a82eb966b0c4 -52a09eab6116f2722064d314ae433b3d6e81d2436e93fdf446112663cde93b87 -9c8be44beb45f18e2c78fee9b016033f01ecda51b9b142091fa69f65ab784d2c -5ad8d34be6f7f1464adfc1e0ef3f7848f40d3bdea4412758f2fcb655c93d8f4d -f6fa48fc5aa4b75dd1c017ab79ac9d737233a6d668f5364ccf47786debd37334 -9c10c9e6efbe78430a61f71c89948aa32cdc3cc7338cf994147819ce7ab23450 -c8f7d9b94c3bb377d17a3fa204b601526317824b142ff6bc843fa7815ece89c0 -839573f234dac8d80cc571a045353d61db904a4398d8ef3df5ac -""" -)) - -# -# openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der -outform DER -out keyenc.der -# hexdump -v -e '32/1 "%02x" "\n"' keyenc.der -# -wrapped_enc_keys.append(( -'skip encryption', # pbeWithMD5AndDES-CBC, only decoding is supported --1, -"", -"", -""" -308201f1301b06092a864886f70d010503300e0408f9b990c89af1d41b020208 -00048201d0c6267fe8592903891933d559e71a7ca68b2e39150f19daca0f7921 -52f97e249d72f670d5140e9150433310ed7c7ee51927693fd39884cb9551cea5 -a7b746f7edf199f8787d4787a35dad930d7db057b2118851211b645ac8b90fa6 -b0e7d49ac8567cbd5fff226e87aa9129a0f52c45e9307752e8575c3b0ff756b7 -31fda6942d15ecb6b27ea19370ccc79773f47891e80d22b440d81259c4c28eac -e0ca839524116bcf52d8c566e49a95ddb0e5493437279a770a39fd333f3fca91 -55884fad0ba5aaf273121f893059d37dd417da7dcfd0d6fa7494968f13b2cc95 -65633f2c891340193e5ec00e4ee0b0e90b3b93da362a4906360845771ade1754 -9df79140be5993f3424c012598eadd3e7c7c0b4db2c72cf103d7943a5cf61420 -93370b9702386c3dd4eb0a47f34b579624a46a108b2d13921fa1b367495fe345 -6aa128aa70f8ca80ae13eb301e96c380724ce67c54380bbea2316c1faf4d058e -b4ca2e23442047606b9bc4b3bf65b432cb271bea4eb35dd3eb360d3be8612a87 -a50e96a2264490aeabdc07c6e78e5dbf4fe3388726d0e2a228346bf3c2907d68 -2a6276b22ae883fb30fa611f4e4193e7a08480fcd7db48308bacbd72bf4807aa -11fd394859f97d22982f7fe890b2e2a0f7e7ffb693 -""" -)) - -# -# openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der -# -outform DER -out keyenc.der -v1 PBE-SHA1-RC2-64 -# hexdump -v -e '32/1 "%02x" "\n"' keyenc.der -# -wrapped_enc_keys.append(( -'skip encryption', # pbeWithSHA1AndRC2-CBC, only decoding is supported --1, -"", -"", -""" -308201f1301b06092a864886f70d01050b300e04083ee943bdae185008020208 -00048201d0e4614d9371d3ff10ceabc2f6a7a13a0f449f9a714144e46518ea55 -e3e6f0cde24031d01ef1f37ec40081449ef01914faf45983dde0d2bc496712de -8dd15a5527dff4721d9016c13f34fb93e3ce68577e30146266d71b539f854e56 -753a192cf126ed4812734d86f81884374f1100772f78d0646e9946407637c565 -d070acab413c55952f7237437f2e48cae7fa0ff8d370de2bf446dd08049a3663 -d9c813ac197468c02e2b687e7ca994cf7f03f01b6eca87dbfed94502c2094157 -ea39f73fe4e591df1a68b04d19d9adab90bb9898467c1464ad20bf2b8fb9a5ff -d3ec91847d1c67fd768a4b9cfb46572eccc83806601372b6fad0243f58f623b7 -1c5809dea0feb8278fe27e5560eed8448dc93f5612f546e5dd7c5f6404365eb2 -5bf3396814367ae8b15c5c432b57eaed1f882c05c7f6517ee9e42b87b7b8d071 -9d6125d1b52f7b2cca1f6bd5f584334bf90bce1a7d938274cafe27b68e629698 -b16e27ae528db28593af9adcfccbebb3b9e1f2af5cd5531b51968389caa6c091 -e7de1f1b96f0d258e54e540d961a7c0ef51fda45d6da5fddd33e9bbfd3a5f8d7 -d7ab2e971de495cddbc86d38444fee9f0ac097b00adaf7802dabe0cff5b43b45 -4f26b7b547016f89be52676866189911c53e2f2477""" -)) - -# -# openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der -# -outform DER -out keyenc.der -v1 PBE-MD5-RC2-64 -# hexdump -v -e '32/1 "%02x" "\n"' keyenc.der -# -wrapped_enc_keys.append(( -'skip encryption', # pbeWithMD5AndRC2-CBC, only decoding is supported --1, -"", -"", -""" -308201f1301b06092a864886f70d010506300e0408f5cd2fee56d9b4b8020208 -00048201d086454942d6166a19d6b108465bd111e7080911f573d54b1369c676 -df28600e84936bfec04f91023ff16499e2e07178c340904f12ffa6886ab66228 -32bf43c2bff5a0ed14e765918cf5fc543ad49566246f7eb3fc044fa5a9c25f40 -8fc8c8296b91658d3bb1067c0aba008c4fefd9e2bcdbbbd63fdc8085482bccf4 -f150cec9a084259ad441a017e5d81a1034ef2484696a7a50863836d0eeda45cd -8cee8ecabfed703f8d9d4bbdf3a767d32a0ccdc38550ee2928d7fe3fa27eda5b -5c7899e75ad55d076d2c2d3c37d6da3d95236081f9671dab9a99afdb1cbc890e -332d1a91105d9a8ce08b6027aa07367bd1daec3059cb51f5d896124da16971e4 -0ca4bcadb06c854bdf39f42dd24174011414e51626d198775eff3449a982df7b -ace874e77e045eb6d7c3faef0750792b29a068a6291f7275df1123fac5789c51 -27ace42836d81633faf9daf38f6787fff0394ea484bbcd465b57d4dbee3cf8df -b77d1db287b3a6264c466805be5a4fe85cfbca180699859280f2dd8e2c2c10b5 -7a7d2ac670c6039d41952fbb0e4f99b560ebe1d020e1b96d02403283819c00cc -529c51f0b0101555e4c58002ba3c6e3c12e3fde1aec94382792e96d9666a2b33 -3dc397b22ecab67ee38a552fec29a1d4ff8719c748""" -)) - -# -# openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der -# -outform DER -out keyenc.der -v1 PBE-SHA1-DES -# hexdump -v -e '32/1 "%02x" "\n"' keyenc.der -# -wrapped_enc_keys.append(( -'skip encryption', # pbeWithSHA1AndDES-CBC, only decoding is supported --1, -"", -"", -""" -308201f1301b06092a864886f70d01050a300e04089bacc9cf1e8f734e020208 -00048201d03e502f3ceafe8fd19ab2939576bfdded26d719b2441db1459688f5 -9673218b41ec1f739edf1e460bd927bc28470c87b2d4fc8ea02ba17b47a63c49 -c5c1bee40529dadfd3ef8b4472c730bc136678c78abfb34670ec9d7dcd17ee3f -892f93f2629e6e0f4b24ecb9f954069bf722f466dece3913bb6abbd2c471d9a5 -c5eea89b14aaccda43d30b0dd0f6eb6e9850d9747aa8aa8414c383ad01c374ee -26d3552abec9ba22669cc9622ccf2921e3d0c8ecd1a70e861956de0bec6104b5 -b649ac994970c83f8a9e84b14a7dff7843d4ca3dd4af87cea43b5657e15ae0b5 -a940ce5047f006ab3596506600724764f23757205fe374fee04911336d655acc -03e159ec27789191d1517c4f3f9122f5242d44d25eab8f0658cafb928566ca0e -8f6589aa0c0ab13ca7a618008ae3eafd4671ee8fe0b562e70b3623b0e2a16eee -97fd388087d2e03530c9fe7db6e52eccc7c48fd701ede35e08922861a9508d12 -bc8bbf24f0c6bee6e63dbcb489b603d4c4a78ce45bf2eab1d5d10456c42a65a8 -3a606f4e4b9b46eb13b57f2624b651859d3d2d5192b45dbd5a2ead14ff20ca76 -48f321309aa56d8c0c4a192b580821cc6c70c75e6f19d1c5414da898ec4dd39d -b0eb93d6ba387a80702dfd2db610757ba340f63230 -""" -)) - -# -# openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der -# -outform DER -out keyenc.der -v2 aes128 -# hexdump -v -e '32/1 "%02x" "\n"' keyenc.der -# -wrapped_enc_keys.append(( -'PBKDF2WithHMAC-SHA1AndAES128-CBC', -2048, -"4F66EE5D3BCD531FE6EBF4B4E73016B8", # IV -"479F25156176C53A", # Salt -""" -3082021f304906092a864886f70d01050d303c301b06092a864886f70d01050c -300e0408479f25156176c53a02020800301d060960864801650304010204104f -66ee5d3bcd531fe6ebf4b4e73016b8048201d0e33cfa560423f589d097d21533 -3b880a5ebac5b2ac58b4e73b0d787aee7764f034fe34ca1d1bd845c0a7c3316f -afbfb2129e03dcaf5a5031394206492828dacef1e04639bee5935e0f46114202 -10bc6c37182f4889be11c5d0486c398f4be952e5740f65de9d8edeb275e2b406 -e19bc29ad5ebb97fa536344fc3d84c7e755696f12b810898de4e6f069b8a81c8 -0aab0d45d7d062303aaa4a10c2ce84fdb5a03114039cfe138e38bb15b2ced717 -93549cdad85e730b14d9e2198b663dfdc8d04a4349eb3de59b076ad40b116d4a -25ed917c576bc7c883c95ef0f1180e28fc9981bea069594c309f1aa1b253ceab -a2f0313bb1372bcb51a745056be93d77a1f235a762a45e8856512d436b2ca0f7 -dd60fbed394ba28978d2a2b984b028529d0a58d93aba46c6bbd4ac1e4013cbaa -63b00988bc5f11ccc40141c346762d2b28f64435d4be98ec17c1884985e3807e -e550db606600993efccf6de0dfc2d2d70b5336a3b018fa415d6bdd59f5777118 -16806b7bc17c4c7e20ad7176ebfa5a1aa3f6bc10f04b77afd443944642ac9cca -d740e082b4a3bbb8bafdd34a0b3c5f2f3c2aceccccdccd092b78994b845bfa61 -706c3b9df5165ed1dbcbf1244fe41fc9bf993f52f7658e2f87e1baaeacb0f562 -9d905c -""" -)) - -# -# openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der -# -outform DER -out keyenc.der -v2 aes192 -# hexdump -v -e '32/1 "%02x" "\n"' keyenc.der -# -wrapped_enc_keys.append(( -'PBKDF2WithHMAC-SHA1AndAES192-CBC', -2048, -"5CFC2A4FF7B63201A4A8A5B021148186", # IV -"D718541C264944CE", # Salt -""" -3082021f304906092a864886f70d01050d303c301b06092a864886f70d01050c -300e0408d718541c264944ce02020800301d060960864801650304011604105c -fc2a4ff7b63201a4a8a5b021148186048201d08e74aaa21b8bcfb15b9790fe95 -b0e09ddb0f189b6fb1682fdb9f122b804650ddec3c67a1df093a828b3e5fbcc6 -286abbcc5354c482fd796d972e919ca8a5eba1eaa2293af1d648013ddad72106 -75622264dfba55dafdda39e338f058f1bdb9846041ffff803797d3fdf3693135 -8a192729ea8346a7e5e58e925a2e2e4af0818581859e8215d87370eb4194a5ff -bae900857d4c591dbc651a241865a817eaede9987c9f9ae4f95c0bf930eea88c -4d7596e535ffb7ca369988aba75027a96b9d0bc9c8b0b75f359067fd145a378b -02aaa15e9db7a23176224da48a83249005460cc6e429168657f2efa8b1af7537 -d7d7042f2d683e8271b21d591090963eeb57aea6172f88da139e1614d6a7d1a2 -1002d5a7a93d6d21156e2b4777f6fc069287a85a1538c46b7722ccde591ab55c -630e1ceeb1ac42d1b41f3f654e9da86b5efced43775ea68b2594e50e4005e052 -0fe753c0898120c2c07265367ff157f6538a1e4080d6f9d1ca9eb51939c9574e -f2e4e1e87c1434affd5808563cddd376776dbbf790c6a40028f311a8b58dafa2 -0970ed34acd6e3e89d063987893b2b9570ddb8cc032b05a723bba9444933ebf3 -c624204be72f4190e0245197d0cb772bec933fd8442445f9a28bd042d5a3a1e9 -9a8a07 -""" -)) - -# -# openssl pkcs8 -topk8 -passin pass:TestTest -inform DER -in key.der -# -outform DER -out keyenc.der -v2 aes192 -# hexdump -v -e '32/1 "%02x" "\n"' keyenc.der -# -wrapped_enc_keys.append(( -'PBKDF2WithHMAC-SHA1AndAES256-CBC', -2048, -"323351F94462AC563E053A056252C2C4", # IV -"02A6CD0D12E727B5", # Salt -""" -3082021f304906092a864886f70d01050d303c301b06092a864886f70d01050c -300e040802a6cd0d12e727b502020800301d060960864801650304012a041032 -3351f94462ac563e053a056252c2c4048201d07f4ef1c7be21aae738a20c5632 -b8bdbbb9083b6e7f68822267b1f481fd27fdafd61a90660de6e4058790e4c912 -bf3f319a7c37e6eb3d956daaa143865020d554bf6215e8d7492359aaeef45d6e -d85a686ed26c0bf7c18d071d827a86f0b73e1db0c0e7f3d42201544093302a90 -551ad530692468c47ac15c69500b8ca67d4a17b64d15cecc035ae50b768a36cf -07c395afa091e9e6f86f665455fbdc1b21ad79c0908b73da5de75a9b43508d5d -44dc97a870cd3cd9f01ca24452e9b11c1b4982946702cfcbfda5b2fcc0203fb5 -0b52a115760bd635c94d4c95ac2c640ee9a04ffaf6ccff5a8d953dd5d88ca478 -c377811c521f2191639c643d657a9e364af88bb7c14a356c2b0b4870a23c2f54 -d41f8157afff731471dccc6058b15e1151bcf84b39b5e622a3a1d65859c912a5 -591b85e034a1f6af664f030a6bfc8c3d20c70f32b54bcf4da9c2da83cef49cf8 -e9a74f0e5d358fe50b88acdce6a9db9a7ad61536212fc5f877ebfc7957b8bda4 -b1582a0f10d515a20ee06cf768db9c977aa6fbdca7540d611ff953012d009dac -e8abd059f8e8ffea637c9c7721f817aaf0bb23403e26a0ef0ff0e2037da67d41 -af728481f53443551a9bff4cea023164e9622b5441a309e1f4bff98e5bf76677 -8d7cd9 -""" -)) - -def txt2bin(inputs): - s = b('').join([b(x) for x in inputs if not (x in '\n\r\t ')]) - return unhexlify(s) - -class Rng: - def __init__(self, output): - self.output=output - self.idx=0 - def __call__(self, n): - output = self.output[self.idx:self.idx+n] - self.idx += n - return output - -class PKCS8_Decrypt(unittest.TestCase): - - def setUp(self): - self.oid_key = oid_key - self.clear_key = txt2bin(clear_key) - self.wrapped_clear_key = txt2bin(wrapped_clear_key) - self.wrapped_enc_keys = [] - for t in wrapped_enc_keys: - self.wrapped_enc_keys.append(( - t[0], - t[1], - txt2bin(t[2]), - txt2bin(t[3]), - txt2bin(t[4]) - )) - - ### NO ENCRYTION - - def test1(self): - """Verify unwrapping w/o encryption""" - res1, res2, res3 = PKCS8.unwrap(self.wrapped_clear_key) - self.assertEqual(res1, self.oid_key) - self.assertEqual(res2, self.clear_key) - - def test2(self): - """Verify wrapping w/o encryption""" - wrapped = PKCS8.wrap(self.clear_key, self.oid_key) - res1, res2, res3 = PKCS8.unwrap(wrapped) - self.assertEqual(res1, self.oid_key) - self.assertEqual(res2, self.clear_key) - - ## ENCRYPTION - - def test3(self): - """Verify unwrapping with encryption""" - - for t in self.wrapped_enc_keys: - res1, res2, res3 = PKCS8.unwrap(t[4], b("TestTest")) - self.assertEqual(res1, self.oid_key) - self.assertEqual(res2, self.clear_key) - - def test4(self): - """Verify wrapping with encryption""" - - for t in self.wrapped_enc_keys: - if t[0] == 'skip encryption': - continue - rng = Rng(t[2]+t[3]) - params = { 'iteration_count':t[1] } - wrapped = PKCS8.wrap( - self.clear_key, - self.oid_key, - b("TestTest"), - protection=t[0], - prot_params=params, - key_params=None, - randfunc=rng) - self.assertEqual(wrapped, t[4]) - -def get_tests(config={}): - from Crypto.SelfTest.st_common import list_test_cases - listTests = [] - listTests += list_test_cases(PKCS8_Decrypt) - return listTests - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') - diff --git a/Crypto/SelfTest/Math/__init__.py b/Crypto/SelfTest/Math/__init__.py deleted file mode 100644 index 18e83d1..0000000 --- a/Crypto/SelfTest/Math/__init__.py +++ /dev/null @@ -1,49 +0,0 @@ -# -# SelfTest/Math/__init__.py: Self-test for math module -# -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -"""Self-test for Math""" - -def get_tests(config={}): - tests = [] - from Crypto.SelfTest.Math import test_Numbers - from Crypto.SelfTest.Math import test_Primality - from Crypto.SelfTest.Math import test_modexp - tests += test_Numbers.get_tests(config=config) - tests += test_Primality.get_tests(config=config) - tests += test_modexp.get_tests(config=config) - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/Math/__pycache__/__init__.cpython-36.pyc b/Crypto/SelfTest/Math/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index ae742c2..0000000 Binary files a/Crypto/SelfTest/Math/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Math/__pycache__/test_Numbers.cpython-36.pyc b/Crypto/SelfTest/Math/__pycache__/test_Numbers.cpython-36.pyc deleted file mode 100644 index 803e469..0000000 Binary files a/Crypto/SelfTest/Math/__pycache__/test_Numbers.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Math/__pycache__/test_Primality.cpython-36.pyc b/Crypto/SelfTest/Math/__pycache__/test_Primality.cpython-36.pyc deleted file mode 100644 index b590d5a..0000000 Binary files a/Crypto/SelfTest/Math/__pycache__/test_Primality.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Math/__pycache__/test_modexp.cpython-36.pyc b/Crypto/SelfTest/Math/__pycache__/test_modexp.cpython-36.pyc deleted file mode 100644 index 0ab23ad..0000000 Binary files a/Crypto/SelfTest/Math/__pycache__/test_modexp.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Math/test_Numbers.py b/Crypto/SelfTest/Math/test_Numbers.py deleted file mode 100644 index 058a6c7..0000000 --- a/Crypto/SelfTest/Math/test_Numbers.py +++ /dev/null @@ -1,774 +0,0 @@ -# -# SelfTest/Math/test_Numbers.py: Self-test for Numbers module -# -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -"""Self-test for Math.Numbers""" - -import sys -import unittest - -from Crypto.SelfTest.st_common import list_test_cases - -from Crypto.Util.py3compat import * - -from Crypto.Math._IntegerNative import IntegerNative - - -class TestIntegerBase(unittest.TestCase): - - def setUp(self): - raise NotImplementedError("To be implemented") - - def Integers(self, *arg): - return map(self.Integer, arg) - - def test_init_and_equality(self): - Integer = self.Integer - - v1 = Integer(23) - v2 = Integer(v1) - v3 = Integer(-9) - self.assertRaises(ValueError, Integer, 1.0) - - v4 = Integer(10**10) - v5 = Integer(-10**10) - self.assertEqual(v1, v1) - self.assertEqual(v1, 23) - self.assertEqual(v1, v2) - self.assertEqual(v3, -9) - self.assertEqual(v4, 10 ** 10) - self.assertEqual(v5, -10 ** 10) - - self.failIf(v1 == v4) - - # Init and comparison between Integer's - v6 = Integer(v1) - self.assertEqual(v1, v6) - - self.failIf(Integer(0) == None) - - def test_conversion_to_int(self): - v1, v2 = self.Integers(-23, 2 ** 1000) - self.assertEqual(int(v1), -23) - self.assertEqual(int(v2), 2 ** 1000) - - def test_equality_with_ints(self): - v1, v2, v3 = self.Integers(23, -89, 2 ** 1000) - self.failUnless(v1 == 23) - self.failUnless(v2 == -89) - self.failIf(v1 == 24) - self.failUnless(v3 == 2 ** 1000) - - def test_conversion_to_str(self): - v1, v2, v3, v4 = self.Integers(20, 0, -20, 2 ** 1000) - self.failUnless(str(v1) == "20") - self.failUnless(str(v2) == "0") - self.failUnless(str(v3) == "-20") - self.failUnless(str(v4) == "10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376") - - def test_repr(self): - v1, v2 = self.Integers(-1, 2**80) - self.assertEqual(repr(v1), "Integer(-1)") - self.assertEqual(repr(v2), "Integer(1208925819614629174706176)") - - def test_conversion_to_bytes(self): - Integer = self.Integer - - v1 = Integer(0x17) - self.assertEqual(b("\x17"), v1.to_bytes()) - - v2 = Integer(0xFFFF) - self.assertEqual(b("\xFF\xFF"), v2.to_bytes()) - self.assertEqual(b("\x00\xFF\xFF"), v2.to_bytes(3)) - self.assertRaises(ValueError, v2.to_bytes, 1) - - v3 = Integer(-90) - self.assertRaises(ValueError, v3.to_bytes) - - def test_conversion_from_bytes(self): - Integer = self.Integer - - v1 = Integer.from_bytes(b("\x00")) - self.failUnless(isinstance(v1, Integer)) - self.assertEqual(0, v1) - - v2 = Integer.from_bytes(b("\x00\x00")) - self.assertEqual(0, v2) - - v3 = Integer.from_bytes(b("\xFF\xFF")) - self.assertEqual(0xFFFF, v3) - - def test_inequality(self): - # Test Integer!=Integer and Integer!=int - v1, v2, v3, v4 = self.Integers(89, 89, 90, -8) - self.failUnless(v1 != v3) - self.failUnless(v1 != 90) - self.failIf(v1 != v2) - self.failIf(v1 != 89) - self.failUnless(v1 != v4) - self.failUnless(v4 != v1) - self.failUnless(self.Integer(0) != None) - - def test_less_than(self): - # Test IntegerInteger and Integer>int - v1, v2, v3, v4, v5 = self.Integers(13, 13, 14, -8, 2 ** 10) - self.failUnless(v3 > v1) - self.failUnless(v3 > 13) - self.failIf(v1 > v1) - self.failIf(v1 > v2) - self.failIf(v1 > 13) - self.failUnless(v1 > v4) - self.failIf(v4 > v1) - self.failUnless(v5 > v1) - self.failIf(v1 > v5) - - def test_more_than_or_equal(self): - # Test Integer>=Integer and Integer>=int - v1, v2, v3, v4 = self.Integers(13, 13, 14, -4) - self.failUnless(v3 >= v1) - self.failUnless(v3 >= 13) - self.failUnless(v1 >= v2) - self.failUnless(v1 >= v1) - self.failUnless(v1 >= 13) - self.failIf(v4 >= v1) - - def test_bool(self): - v1, v2, v3, v4 = self.Integers(0, 10, -9, 2 ** 10) - self.assertFalse(v1) - self.assertFalse(bool(v1)) - self.failUnless(v2) - self.failUnless(bool(v2)) - self.failUnless(v3) - self.failUnless(v4) - - def test_is_negative(self): - v1, v2, v3, v4, v5 = self.Integers(-3 ** 100, -3, 0, 3, 3**100) - self.failUnless(v1.is_negative()) - self.failUnless(v2.is_negative()) - self.failIf(v4.is_negative()) - self.failIf(v5.is_negative()) - - def test_addition(self): - # Test Integer+Integer and Integer+int - v1, v2, v3 = self.Integers(7, 90, -7) - self.failUnless(isinstance(v1 + v2, self.Integer)) - self.assertEqual(v1 + v2, 97) - self.assertEqual(v1 + 90, 97) - self.assertEqual(v1 + v3, 0) - self.assertEqual(v1 + (-7), 0) - self.assertEqual(v1 + 2 ** 10, 2 ** 10 + 7) - - def test_subtraction(self): - # Test Integer-Integer and Integer-int - v1, v2, v3 = self.Integers(7, 90, -7) - self.failUnless(isinstance(v1 - v2, self.Integer)) - self.assertEqual(v2 - v1, 83) - self.assertEqual(v2 - 7, 83) - self.assertEqual(v2 - v3, 97) - self.assertEqual(v1 - (-7), 14) - self.assertEqual(v1 - 2 ** 10, 7 - 2 ** 10) - - def test_multiplication(self): - # Test Integer-Integer and Integer-int - v1, v2, v3, v4 = self.Integers(4, 5, -2, 2 ** 10) - self.failUnless(isinstance(v1 * v2, self.Integer)) - self.assertEqual(v1 * v2, 20) - self.assertEqual(v1 * 5, 20) - self.assertEqual(v1 * -2, -8) - self.assertEqual(v1 * 2 ** 10, 4 * (2 ** 10)) - - def test_floor_div(self): - v1, v2, v3 = self.Integers(3, 8, 2 ** 80) - self.failUnless(isinstance(v1 // v2, self.Integer)) - self.assertEqual(v2 // v1, 2) - self.assertEqual(v2 // 3, 2) - self.assertEqual(v2 // -3, -3) - self.assertEqual(v3 // 2 ** 79, 2) - self.assertRaises(ZeroDivisionError, lambda: v1 // 0) - - def test_remainder(self): - # Test Integer%Integer and Integer%int - v1, v2, v3 = self.Integers(23, 5, -4) - self.failUnless(isinstance(v1 % v2, self.Integer)) - self.assertEqual(v1 % v2, 3) - self.assertEqual(v1 % 5, 3) - self.assertEqual(v3 % 5, 1) - self.assertEqual(v1 % 2 ** 10, 23) - self.assertRaises(ZeroDivisionError, lambda: v1 % 0) - self.assertRaises(ValueError, lambda: v1 % -6) - - def test_simple_exponentiation(self): - v1, v2, v3 = self.Integers(4, 3, -2) - self.failUnless(isinstance(v1 ** v2, self.Integer)) - self.assertEqual(v1 ** v2, 64) - self.assertEqual(pow(v1, v2), 64) - self.assertEqual(v1 ** 3, 64) - self.assertEqual(pow(v1, 3), 64) - self.assertEqual(v3 ** 2, 4) - self.assertEqual(v3 ** 3, -8) - - self.assertRaises(ValueError, pow, v1, -3) - - def test_modular_exponentiation(self): - v1, v2, v3 = self.Integers(23, 5, 17) - - self.failUnless(isinstance(pow(v1, v2, v3), self.Integer)) - self.assertEqual(pow(v1, v2, v3), 7) - self.assertEqual(pow(v1, 5, v3), 7) - self.assertEqual(pow(v1, v2, 17), 7) - self.assertEqual(pow(v1, 5, 17), 7) - self.assertEqual(pow(v1, 0, 17), 1) - self.assertEqual(pow(v1, 1, 2 ** 80), 23) - self.assertEqual(pow(v1, 2 ** 80, 89298), 17689) - - self.assertRaises(ZeroDivisionError, pow, v1, 5, 0) - self.assertRaises(ValueError, pow, v1, 5, -4) - self.assertRaises(ValueError, pow, v1, -3, 8) - - def test_inplace_exponentiation(self): - v1 = self.Integer(4) - v1.inplace_pow(2) - self.assertEqual(v1, 16) - - v1 = self.Integer(4) - v1.inplace_pow(2, 15) - self.assertEqual(v1, 1) - - def test_abs(self): - v1, v2, v3, v4, v5 = self.Integers(-2 ** 100, -2, 0, 2, 2 ** 100) - self.assertEqual(abs(v1), 2 ** 100) - self.assertEqual(abs(v2), 2) - self.assertEqual(abs(v3), 0) - self.assertEqual(abs(v4), 2) - self.assertEqual(abs(v5), 2 ** 100) - - def test_sqrt(self): - v1, v2, v3, v4 = self.Integers(-2, 0, 49, 10**100) - - self.assertRaises(ValueError, v1.sqrt) - self.assertEqual(v2.sqrt(), 0) - self.assertEqual(v3.sqrt(), 7) - self.assertEqual(v4.sqrt(), 10**50) - - def test_sqrt_module(self): - - # Invalid modulus (non positive) - self.assertRaises(ValueError, self.Integer(5).sqrt, 0) - self.assertRaises(ValueError, self.Integer(5).sqrt, -1) - - # Simple cases - assert self.Integer(0).sqrt(5) == 0 - assert self.Integer(1).sqrt(5) in (1, 4) - - # Test with all quadratic residues in several fields - for p in (11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53): - for i in range(0, p): - square = i**2 % p - res = self.Integer(square).sqrt(p) - assert res in (i, p - i) - - # 2 is a non-quadratic reside in Z_11 - self.assertRaises(ValueError, self.Integer(2).sqrt, 11) - - # 10 is not a prime - self.assertRaises(ValueError, self.Integer(4).sqrt, 10) - - # 5 is square residue of 4 and 7 - assert self.Integer(5 - 11).sqrt(11) in (4, 7) - assert self.Integer(5 + 11).sqrt(11) in (4, 7) - - def test_in_place_add(self): - v1, v2 = self.Integers(10, 20) - - v1 += v2 - self.assertEqual(v1, 30) - v1 += 10 - self.assertEqual(v1, 40) - v1 += -1 - self.assertEqual(v1, 39) - v1 += 2 ** 1000 - self.assertEqual(v1, 39 + 2 ** 1000) - - def test_in_place_sub(self): - v1, v2 = self.Integers(10, 20) - - v1 -= v2 - self.assertEqual(v1, -10) - v1 -= -100 - self.assertEqual(v1, 90) - v1 -= 90000 - self.assertEqual(v1, -89910) - v1 -= -100000 - self.assertEqual(v1, 10090) - - def test_in_place_mul(self): - v1, v2 = self.Integers(3, 5) - - v1 *= v2 - self.assertEqual(v1, 15) - v1 *= 2 - self.assertEqual(v1, 30) - v1 *= -2 - self.assertEqual(v1, -60) - v1 *= 2 ** 1000 - self.assertEqual(v1, -60 * (2 ** 1000)) - - def test_in_place_modulus(self): - v1, v2 = self.Integers(20, 7) - - v1 %= v2 - self.assertEqual(v1, 6) - v1 %= 2 ** 1000 - self.assertEqual(v1, 6) - v1 %= 2 - self.assertEqual(v1, 0) - def t(): - v3 = self.Integer(9) - v3 %= 0 - self.assertRaises(ZeroDivisionError, t) - - def test_and(self): - v1, v2, v3 = self.Integers(0xF4, 0x31, -0xF) - self.failUnless(isinstance(v1 & v2, self.Integer)) - self.assertEqual(v1 & v2, 0x30) - self.assertEqual(v1 & 0x31, 0x30) - self.assertEqual(v1 & v3, 0xF0) - self.assertEqual(v1 & -0xF, 0xF0) - self.assertEqual(v3 & -0xF, -0xF) - self.assertEqual(v2 & (2 ** 1000 + 0x31), 0x31) - - def test_or(self): - v1, v2, v3 = self.Integers(0x40, 0x82, -0xF) - self.failUnless(isinstance(v1 | v2, self.Integer)) - self.assertEqual(v1 | v2, 0xC2) - self.assertEqual(v1 | 0x82, 0xC2) - self.assertEqual(v2 | v3, -0xD) - self.assertEqual(v2 | 2 ** 1000, 2 ** 1000 + 0x82) - - def test_right_shift(self): - v1, v2, v3 = self.Integers(0x10, 1, -0x10) - self.assertEqual(v1 >> 0, v1) - self.failUnless(isinstance(v1 >> v2, self.Integer)) - self.assertEqual(v1 >> v2, 0x08) - self.assertEqual(v1 >> 1, 0x08) - self.assertRaises(ValueError, lambda: v1 >> -1) - self.assertEqual(v1 >> (2 ** 1000), 0) - - self.assertEqual(v3 >> 1, -0x08) - self.assertEqual(v3 >> (2 ** 1000), -1) - - def test_in_place_right_shift(self): - v1, v2, v3 = self.Integers(0x10, 1, -0x10) - v1 >>= 0 - self.assertEqual(v1, 0x10) - v1 >>= 1 - self.assertEqual(v1, 0x08) - v1 >>= v2 - self.assertEqual(v1, 0x04) - v3 >>= 1 - self.assertEqual(v3, -0x08) - def l(): - v4 = self.Integer(0x90) - v4 >>= -1 - self.assertRaises(ValueError, l) - def m1(): - v4 = self.Integer(0x90) - v4 >>= 2 ** 1000 - return v4 - self.assertEqual(0, m1()) - def m2(): - v4 = self.Integer(-1) - v4 >>= 2 ** 1000 - return v4 - self.assertEqual(-1, m2()) - - def _test_left_shift(self): - v1, v2, v3 = self.Integers(0x10, 1, -0x10) - self.assertEqual(v1 << 0, v1) - self.failUnless(isinstance(v1 << v2, self.Integer)) - self.assertEqual(v1 << v2, 0x20) - self.assertEqual(v1 << 1, 0x20) - self.assertEqual(v3 << 1, -0x20) - self.assertRaises(ValueError, lambda: v1 << -1) - self.assertRaises(ValueError, lambda: v1 << (2 ** 1000)) - - def test_in_place_left_shift(self): - v1, v2, v3 = self.Integers(0x10, 1, -0x10) - v1 <<= 0 - self.assertEqual(v1, 0x10) - v1 <<= 1 - self.assertEqual(v1, 0x20) - v1 <<= v2 - self.assertEqual(v1, 0x40) - v3 <<= 1 - self.assertEqual(v3, -0x20) - def l(): - v4 = self.Integer(0x90) - v4 <<= -1 - self.assertRaises(ValueError, l) - def m(): - v4 = self.Integer(0x90) - v4 <<= 2 ** 1000 - self.assertRaises(ValueError, m) - - - def test_get_bit(self): - v1, v2, v3 = self.Integers(0x102, -3, 1) - self.assertEqual(v1.get_bit(0), 0) - self.assertEqual(v1.get_bit(1), 1) - self.assertEqual(v1.get_bit(v3), 1) - self.assertEqual(v1.get_bit(8), 1) - self.assertEqual(v1.get_bit(9), 0) - - self.assertRaises(ValueError, v1.get_bit, -1) - self.assertEqual(v1.get_bit(2 ** 1000), 0) - - self.assertRaises(ValueError, v2.get_bit, -1) - self.assertRaises(ValueError, v2.get_bit, 0) - self.assertRaises(ValueError, v2.get_bit, 1) - self.assertRaises(ValueError, v2.get_bit, 2 * 1000) - - def test_odd_even(self): - v1, v2, v3, v4, v5 = self.Integers(0, 4, 17, -4, -17) - - self.failUnless(v1.is_even()) - self.failUnless(v2.is_even()) - self.failIf(v3.is_even()) - self.failUnless(v4.is_even()) - self.failIf(v5.is_even()) - - self.failIf(v1.is_odd()) - self.failIf(v2.is_odd()) - self.failUnless(v3.is_odd()) - self.failIf(v4.is_odd()) - self.failUnless(v5.is_odd()) - - def test_size_in_bits(self): - v1, v2, v3, v4 = self.Integers(0, 1, 0x100, -90) - self.assertEqual(v1.size_in_bits(), 1) - self.assertEqual(v2.size_in_bits(), 1) - self.assertEqual(v3.size_in_bits(), 9) - self.assertRaises(ValueError, v4.size_in_bits) - - def test_size_in_bytes(self): - v1, v2, v3, v4, v5, v6 = self.Integers(0, 1, 0xFF, 0x1FF, 0x10000, -9) - self.assertEqual(v1.size_in_bytes(), 1) - self.assertEqual(v2.size_in_bytes(), 1) - self.assertEqual(v3.size_in_bytes(), 1) - self.assertEqual(v4.size_in_bytes(), 2) - self.assertEqual(v5.size_in_bytes(), 3) - self.assertRaises(ValueError, v6.size_in_bits) - - def test_perfect_square(self): - - self.failIf(self.Integer(-9).is_perfect_square()) - self.failUnless(self.Integer(0).is_perfect_square()) - self.failUnless(self.Integer(1).is_perfect_square()) - self.failIf(self.Integer(2).is_perfect_square()) - self.failIf(self.Integer(3).is_perfect_square()) - self.failUnless(self.Integer(4).is_perfect_square()) - self.failUnless(self.Integer(39*39).is_perfect_square()) - self.failIf(self.Integer(39*39+1).is_perfect_square()) - - for x in range(100, 1000): - self.failIf(self.Integer(x**2+1).is_perfect_square()) - self.failUnless(self.Integer(x**2).is_perfect_square()) - - def test_fail_if_divisible_by(self): - v1, v2, v3 = self.Integers(12, -12, 4) - - # No failure expected - v1.fail_if_divisible_by(7) - v2.fail_if_divisible_by(7) - v2.fail_if_divisible_by(2 ** 80) - - # Failure expected - self.assertRaises(ValueError, v1.fail_if_divisible_by, 4) - self.assertRaises(ValueError, v1.fail_if_divisible_by, v3) - - def test_multiply_accumulate(self): - v1, v2, v3 = self.Integers(4, 3, 2) - v1.multiply_accumulate(v2, v3) - self.assertEqual(v1, 10) - v1.multiply_accumulate(v2, 2) - self.assertEqual(v1, 16) - v1.multiply_accumulate(3, v3) - self.assertEqual(v1, 22) - v1.multiply_accumulate(1, -2) - self.assertEqual(v1, 20) - v1.multiply_accumulate(-2, 1) - self.assertEqual(v1, 18) - v1.multiply_accumulate(1, 2 ** 1000) - self.assertEqual(v1, 18 + 2 ** 1000) - v1.multiply_accumulate(2 ** 1000, 1) - self.assertEqual(v1, 18 + 2 ** 1001) - - def test_set(self): - v1, v2 = self.Integers(3, 6) - v1.set(v2) - self.assertEqual(v1, 6) - v1.set(9) - self.assertEqual(v1, 9) - v1.set(-2) - self.assertEqual(v1, -2) - v1.set(2 ** 1000) - self.assertEqual(v1, 2 ** 1000) - - def test_inverse(self): - v1, v2, v3, v4, v5, v6 = self.Integers(2, 5, -3, 0, 723872, 3433) - - self.failUnless(isinstance(v1.inverse(v2), self.Integer)) - self.assertEqual(v1.inverse(v2), 3) - self.assertEqual(v1.inverse(5), 3) - self.assertEqual(v3.inverse(5), 3) - self.assertEqual(v5.inverse(92929921), 58610507) - self.assertEqual(v6.inverse(9912), 5353) - - self.assertRaises(ValueError, v2.inverse, 10) - self.assertRaises(ValueError, v1.inverse, -3) - self.assertRaises(ValueError, v4.inverse, 10) - self.assertRaises(ZeroDivisionError, v2.inverse, 0) - - def test_inplace_inverse(self): - v1, v2 = self.Integers(2, 5) - - v1.inplace_inverse(v2) - self.assertEqual(v1, 3) - - def test_gcd(self): - v1, v2, v3, v4 = self.Integers(6, 10, 17, -2) - self.failUnless(isinstance(v1.gcd(v2), self.Integer)) - self.assertEqual(v1.gcd(v2), 2) - self.assertEqual(v1.gcd(10), 2) - self.assertEqual(v1.gcd(v3), 1) - self.assertEqual(v1.gcd(-2), 2) - self.assertEqual(v4.gcd(6), 2) - - def test_lcm(self): - v1, v2, v3, v4, v5 = self.Integers(6, 10, 17, -2, 0) - self.failUnless(isinstance(v1.lcm(v2), self.Integer)) - self.assertEqual(v1.lcm(v2), 30) - self.assertEqual(v1.lcm(10), 30) - self.assertEqual(v1.lcm(v3), 102) - self.assertEqual(v1.lcm(-2), 6) - self.assertEqual(v4.lcm(6), 6) - self.assertEqual(v1.lcm(0), 0) - self.assertEqual(v5.lcm(0), 0) - - def test_jacobi_symbol(self): - - data = ( - (1001, 1, 1), - (19, 45, 1), - (8, 21, -1), - (5, 21, 1), - (610, 987, -1), - (1001, 9907, -1), - (5, 3439601197, -1) - ) - - js = self.Integer.jacobi_symbol - - # Jacobi symbol is always 1 for k==1 or n==1 - for k in range(1, 30): - self.assertEqual(js(k, 1), 1) - for n in range(1, 30, 2): - self.assertEqual(js(1, n), 1) - - # Fail if n is not positive odd - self.assertRaises(ValueError, js, 6, -2) - self.assertRaises(ValueError, js, 6, -1) - self.assertRaises(ValueError, js, 6, 0) - self.assertRaises(ValueError, js, 0, 0) - self.assertRaises(ValueError, js, 6, 2) - self.assertRaises(ValueError, js, 6, 4) - self.assertRaises(ValueError, js, 6, 6) - self.assertRaises(ValueError, js, 6, 8) - - for tv in data: - self.assertEqual(js(tv[0], tv[1]), tv[2]) - self.assertEqual(js(self.Integer(tv[0]), tv[1]), tv[2]) - self.assertEqual(js(tv[0], self.Integer(tv[1])), tv[2]) - - def test_jacobi_symbol_wikipedia(self): - - # Test vectors from https://en.wikipedia.org/wiki/Jacobi_symbol - tv = [ - (3, [(1, 1), (2, -1), (3, 0), (4, 1), (5, -1), (6, 0), (7, 1), (8, -1), (9, 0), (10, 1), (11, -1), (12, 0), (13, 1), (14, -1), (15, 0), (16, 1), (17, -1), (18, 0), (19, 1), (20, -1), (21, 0), (22, 1), (23, -1), (24, 0), (25, 1), (26, -1), (27, 0), (28, 1), (29, -1), (30, 0)]), - (5, [(1, 1), (2, -1), (3, -1), (4, 1), (5, 0), (6, 1), (7, -1), (8, -1), (9, 1), (10, 0), (11, 1), (12, -1), (13, -1), (14, 1), (15, 0), (16, 1), (17, -1), (18, -1), (19, 1), (20, 0), (21, 1), (22, -1), (23, -1), (24, 1), (25, 0), (26, 1), (27, -1), (28, -1), (29, 1), (30, 0)]), - (7, [(1, 1), (2, 1), (3, -1), (4, 1), (5, -1), (6, -1), (7, 0), (8, 1), (9, 1), (10, -1), (11, 1), (12, -1), (13, -1), (14, 0), (15, 1), (16, 1), (17, -1), (18, 1), (19, -1), (20, -1), (21, 0), (22, 1), (23, 1), (24, -1), (25, 1), (26, -1), (27, -1), (28, 0), (29, 1), (30, 1)]), - (9, [(1, 1), (2, 1), (3, 0), (4, 1), (5, 1), (6, 0), (7, 1), (8, 1), (9, 0), (10, 1), (11, 1), (12, 0), (13, 1), (14, 1), (15, 0), (16, 1), (17, 1), (18, 0), (19, 1), (20, 1), (21, 0), (22, 1), (23, 1), (24, 0), (25, 1), (26, 1), (27, 0), (28, 1), (29, 1), (30, 0)]), - (11, [(1, 1), (2, -1), (3, 1), (4, 1), (5, 1), (6, -1), (7, -1), (8, -1), (9, 1), (10, -1), (11, 0), (12, 1), (13, -1), (14, 1), (15, 1), (16, 1), (17, -1), (18, -1), (19, -1), (20, 1), (21, -1), (22, 0), (23, 1), (24, -1), (25, 1), (26, 1), (27, 1), (28, -1), (29, -1), (30, -1)]), - (13, [(1, 1), (2, -1), (3, 1), (4, 1), (5, -1), (6, -1), (7, -1), (8, -1), (9, 1), (10, 1), (11, -1), (12, 1), (13, 0), (14, 1), (15, -1), (16, 1), (17, 1), (18, -1), (19, -1), (20, -1), (21, -1), (22, 1), (23, 1), (24, -1), (25, 1), (26, 0), (27, 1), (28, -1), (29, 1), (30, 1)]), - (15, [(1, 1), (2, 1), (3, 0), (4, 1), (5, 0), (6, 0), (7, -1), (8, 1), (9, 0), (10, 0), (11, -1), (12, 0), (13, -1), (14, -1), (15, 0), (16, 1), (17, 1), (18, 0), (19, 1), (20, 0), (21, 0), (22, -1), (23, 1), (24, 0), (25, 0), (26, -1), (27, 0), (28, -1), (29, -1), (30, 0)]), - (17, [(1, 1), (2, 1), (3, -1), (4, 1), (5, -1), (6, -1), (7, -1), (8, 1), (9, 1), (10, -1), (11, -1), (12, -1), (13, 1), (14, -1), (15, 1), (16, 1), (17, 0), (18, 1), (19, 1), (20, -1), (21, 1), (22, -1), (23, -1), (24, -1), (25, 1), (26, 1), (27, -1), (28, -1), (29, -1), (30, 1)]), - (19, [(1, 1), (2, -1), (3, -1), (4, 1), (5, 1), (6, 1), (7, 1), (8, -1), (9, 1), (10, -1), (11, 1), (12, -1), (13, -1), (14, -1), (15, -1), (16, 1), (17, 1), (18, -1), (19, 0), (20, 1), (21, -1), (22, -1), (23, 1), (24, 1), (25, 1), (26, 1), (27, -1), (28, 1), (29, -1), (30, 1)]), - (21, [(1, 1), (2, -1), (3, 0), (4, 1), (5, 1), (6, 0), (7, 0), (8, -1), (9, 0), (10, -1), (11, -1), (12, 0), (13, -1), (14, 0), (15, 0), (16, 1), (17, 1), (18, 0), (19, -1), (20, 1), (21, 0), (22, 1), (23, -1), (24, 0), (25, 1), (26, 1), (27, 0), (28, 0), (29, -1), (30, 0)]), - (23, [(1, 1), (2, 1), (3, 1), (4, 1), (5, -1), (6, 1), (7, -1), (8, 1), (9, 1), (10, -1), (11, -1), (12, 1), (13, 1), (14, -1), (15, -1), (16, 1), (17, -1), (18, 1), (19, -1), (20, -1), (21, -1), (22, -1), (23, 0), (24, 1), (25, 1), (26, 1), (27, 1), (28, -1), (29, 1), (30, -1)]), - (25, [(1, 1), (2, 1), (3, 1), (4, 1), (5, 0), (6, 1), (7, 1), (8, 1), (9, 1), (10, 0), (11, 1), (12, 1), (13, 1), (14, 1), (15, 0), (16, 1), (17, 1), (18, 1), (19, 1), (20, 0), (21, 1), (22, 1), (23, 1), (24, 1), (25, 0), (26, 1), (27, 1), (28, 1), (29, 1), (30, 0)]), - (27, [(1, 1), (2, -1), (3, 0), (4, 1), (5, -1), (6, 0), (7, 1), (8, -1), (9, 0), (10, 1), (11, -1), (12, 0), (13, 1), (14, -1), (15, 0), (16, 1), (17, -1), (18, 0), (19, 1), (20, -1), (21, 0), (22, 1), (23, -1), (24, 0), (25, 1), (26, -1), (27, 0), (28, 1), (29, -1), (30, 0)]), - (29, [(1, 1), (2, -1), (3, -1), (4, 1), (5, 1), (6, 1), (7, 1), (8, -1), (9, 1), (10, -1), (11, -1), (12, -1), (13, 1), (14, -1), (15, -1), (16, 1), (17, -1), (18, -1), (19, -1), (20, 1), (21, -1), (22, 1), (23, 1), (24, 1), (25, 1), (26, -1), (27, -1), (28, 1), (29, 0), (30, 1)]), - ] - - js = self.Integer.jacobi_symbol - - for n, kj in tv: - for k, j in kj: - self.assertEqual(js(k, n), j) - - def test_hex(self): - v1, = self.Integers(0x10) - self.assertEqual(hex(v1), "0x10") - - -class TestIntegerInt(TestIntegerBase): - - def setUp(self): - self.Integer = IntegerNative - - -class testIntegerRandom(unittest.TestCase): - - def test_random_exact_bits(self): - - for _ in range(1000): - a = IntegerNative.random(exact_bits=8) - self.failIf(a < 128) - self.failIf(a >= 256) - - for bits_value in range(1024, 1024 + 8): - a = IntegerNative.random(exact_bits=bits_value) - self.failIf(a < 2**(bits_value - 1)) - self.failIf(a >= 2**bits_value) - - def test_random_max_bits(self): - - flag = False - for _ in range(1000): - a = IntegerNative.random(max_bits=8) - flag = flag or a < 128 - self.failIf(a>=256) - self.failUnless(flag) - - for bits_value in range(1024, 1024 + 8): - a = IntegerNative.random(max_bits=bits_value) - self.failIf(a >= 2**bits_value) - - def test_random_bits_custom_rng(self): - - class CustomRNG(object): - def __init__(self): - self.counter = 0 - - def __call__(self, size): - self.counter += size - return bchr(0) * size - - custom_rng = CustomRNG() - a = IntegerNative.random(exact_bits=32, randfunc=custom_rng) - self.assertEqual(custom_rng.counter, 4) - - def test_random_range(self): - - func = IntegerNative.random_range - - for x in range(200): - a = func(min_inclusive=1, max_inclusive=15) - self.failUnless(1 <= a <= 15) - - for x in range(200): - a = func(min_inclusive=1, max_exclusive=15) - self.failUnless(1 <= a < 15) - - self.assertRaises(ValueError, func, min_inclusive=1, max_inclusive=2, - max_exclusive=3) - self.assertRaises(ValueError, func, max_inclusive=2, max_exclusive=3) - -def get_tests(config={}): - tests = [] - tests += list_test_cases(TestIntegerInt) - - try: - from Crypto.Math._IntegerGMP import IntegerGMP - - class TestIntegerGMP(TestIntegerBase): - def setUp(self): - self.Integer = IntegerGMP - - tests += list_test_cases(TestIntegerGMP) - except (ImportError, OSError) as e: - if sys.platform == "win32": - sys.stdout.write("Skipping GMP tests on Windows\n") - else: - sys.stdout.write("Skipping GMP tests (%s)\n" % str(e) ) - - try: - from Crypto.Math._IntegerCustom import IntegerCustom - - class TestIntegerCustomModexp(TestIntegerBase): - def setUp(self): - self.Integer = IntegerCustom - - tests += list_test_cases(TestIntegerCustomModexp) - except (ImportError, OSError) as e: - sys.stdout.write("Skipping custom modexp tests (%s)\n" % str(e) ) - - tests += list_test_cases(testIntegerRandom) - return tests - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/Math/test_Primality.py b/Crypto/SelfTest/Math/test_Primality.py deleted file mode 100644 index 38344f3..0000000 --- a/Crypto/SelfTest/Math/test_Primality.py +++ /dev/null @@ -1,118 +0,0 @@ -# -# SelfTest/Math/test_Primality.py: Self-test for Primality module -# -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -"""Self-test for Math.Numbers""" - -import unittest - -from Crypto.SelfTest.st_common import list_test_cases - -from Crypto.Util.py3compat import * - -from Crypto.Math.Numbers import Integer -from Crypto.Math.Primality import ( - PROBABLY_PRIME, COMPOSITE, - miller_rabin_test, lucas_test, - test_probable_prime, - generate_probable_prime, - generate_probable_safe_prime, - ) - - -class TestPrimality(unittest.TestCase): - - primes = (1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 2**127-1, 175637383534939453397801320455508570374088202376942372758907369518414308188137781042871856139027160010343454418881888953150175357127346872102307696660678617989191485418582475696230580407111841072614783095326672517315988762029036079794994990250662362650625650262324085116467511357592728695033227611029693067539) - composites = (0, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 7*23, (2**19-1)*(2**67-1), 9746347772161,) - - def test_miller_rabin(self): - for prime in self.primes: - self.assertEqual(miller_rabin_test(prime, 3), PROBABLY_PRIME) - for composite in self.composites: - self.assertEqual(miller_rabin_test(composite, 3), COMPOSITE) - self.assertRaises(ValueError, miller_rabin_test, -1, 3) - - def test_lucas(self): - for prime in self.primes: - res = lucas_test(prime) - self.assertEqual(res, PROBABLY_PRIME) - for composite in self.composites: - res = lucas_test(composite) - self.assertEqual(res, COMPOSITE) - self.assertRaises(ValueError, lucas_test, -1) - - def test_is_prime(self): - primes = (170141183460469231731687303715884105727, - 19175002942688032928599, - 1363005552434666078217421284621279933627102780881053358473, - 2 ** 521 - 1) - for p in primes: - self.assertEqual(test_probable_prime(p), PROBABLY_PRIME) - - not_primes = ( - 4754868377601046732119933839981363081972014948522510826417784001, - 1334733877147062382486934807105197899496002201113849920496510541601, - 260849323075371835669784094383812120359260783810157225730623388382401, - ) - for np in not_primes: - self.assertEqual(test_probable_prime(np), COMPOSITE) - - from Crypto.Util.number import sieve_base - for p in sieve_base[:100]: - res = test_probable_prime(p) - self.assertEqual(res, PROBABLY_PRIME) - - def test_generate_prime_bit_size(self): - p = generate_probable_prime(exact_bits=512) - self.assertEqual(p.size_in_bits(), 512) - - def test_generate_prime_filter(self): - def ending_with_one(number): - return number % 10 == 1 - - for x in range(20): - q = generate_probable_prime(exact_bits=160, - prime_filter=ending_with_one) - self.assertEqual(q % 10, 1) - - def test_generate_safe_prime(self): - p = generate_probable_safe_prime(exact_bits=161) - self.assertEqual(p.size_in_bits(), 161) - -def get_tests(config={}): - tests = [] - tests += list_test_cases(TestPrimality) - return tests - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/Math/test_modexp.py b/Crypto/SelfTest/Math/test_modexp.py deleted file mode 100644 index b9eb869..0000000 --- a/Crypto/SelfTest/Math/test_modexp.py +++ /dev/null @@ -1,201 +0,0 @@ -# -# SelfTest/Math/test_modexp.py: Self-test for module exponentiation -# -# =================================================================== -# -# Copyright (c) 2017, Helder Eijs -# 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. -# =================================================================== - -"""Self-test for the custom module exponentiation""" - -import unittest - -from Crypto.SelfTest.st_common import list_test_cases - -from Crypto.Util.number import long_to_bytes, bytes_to_long - -from Crypto.Util.py3compat import * - -from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, - create_string_buffer, - get_raw_buffer, - c_size_t, - c_ulonglong) - -from Crypto.Hash import SHAKE128 -from Crypto.Math.Numbers import Integer -from Crypto.Math._IntegerCustom import _raw_montgomery - -from Crypto.Random.random import StrongRandom - - -def create_rng(tag): - rng = StrongRandom(SHAKE128.new(data=tag)) - return rng - -class ExceptionModulus(ValueError): - pass - -def monty_pow(base, exp, modulus): - max_len = len(long_to_bytes(max(base, exp, modulus))) - - base_b, exp_b, modulus_b = [ long_to_bytes(x, max_len) for x in - (base, exp, modulus) ] - - out = create_string_buffer(max_len) - error = _raw_montgomery.monty_pow( - out, - base_b, - exp_b, - modulus_b, - c_size_t(max_len), - c_ulonglong(32) - ) - - if error == 17: - raise ExceptionModulus() - if error: - raise ValueError("monty_pow failed with error: %d" % error) - - result = bytes_to_long(get_raw_buffer(out)) - return result - -exponent1 = 0x2ce0af628901460a419a08ef950d498b9fd6f271a1a52ac293b86fe5c60efe8e8ba93fa1ebe1eb3d614d2e7b328cb60a2591440e163441a190ecf101ceec245f600fffdcf3f5b3a17a7baeacb96a424db1d7ec985e8ec998bb479fecfffed6a75f9a90fc97062fd973303bce855ad7b8d8272a94025e8532be9aabd54a183f303538d2a7e621b4131d59e823a4625f39bd7d518d7784f7c3a8f19061da74974ff42fa1c063dec2db97d461e291a7d6e721708a5229de166c1246363372854e27f3f08ae274bc16bfd205b028a4d81386494433d516dfbb35f495acba5e4e1d1843cb3c3129b6642a85fc7244ce5845fac071c7f622e4ee12ac43fabeeaa0cd01 -modulus1 = 0xd66691b20071be4d66d4b71032b37fa007cfabf579fcb91e50bfc2753b3f0ce7be74e216aef7e26d4ae180bc20d7bd3ea88a6cbf6f87380e613c8979b5b043b200a8ff8856a3b12875e36e98a7569f3852d028e967551000b02c19e9fa52e83115b89309aabb1e1cf1e2cb6369d637d46775ce4523ea31f64ad2794cbc365dd8a35e007ed3b57695877fbf102dbeb8b3212491398e494314e93726926e1383f8abb5889bea954eb8c0ca1c62c8e9d83f41888095c5e645ed6d32515fe0c58c1368cad84694e18da43668c6f43e61d7c9bca633ddcda7aef5b79bc396d4a9f48e2a9abe0836cc455e435305357228e93d25aaed46b952defae0f57339bf26f5a9 - - -class TestModExp(unittest.TestCase): - - def test_small(self): - self.assertEqual(1, monty_pow(11,12,19)) - - def test_large_1(self): - base = 0xfffffffffffffffffffffffffffffffffffffffffffffffffff - expected = pow(base, exponent1, modulus1) - result = monty_pow(base, exponent1, modulus1) - self.assertEqual(result, expected) - - def test_zero_exp(self): - base = 0xfffffffffffffffffffffffffffffffffffffffffffffffffff - result = monty_pow(base, 0, modulus1) - self.assertEqual(result, 1) - - def test_zero_base(self): - result = monty_pow(0, exponent1, modulus1) - self.assertEqual(result, 0) - - def test_zero_modulus(self): - base = 0xfffffffffffffffffffffffffffffffffffffffffffffffff - self.assertRaises(ExceptionModulus, monty_pow, base, exponent1, 0) - self.assertRaises(ExceptionModulus, monty_pow, 0, 0, 0) - - def test_larger_exponent(self): - base = modulus1 - 0xFFFFFFF - expected = pow(base, modulus1<<64, modulus1) - result = monty_pow(base, modulus1<<64, modulus1) - self.assertEqual(result, expected) - - def test_even_modulus(self): - base = modulus1 >> 4 - self.assertRaises(ExceptionModulus, monty_pow, base, exponent1, modulus1-1) - - def test_several_lengths(self): - prng = SHAKE128.new().update(b('Test')) - for length in range(1, 100): - modulus2 = Integer.from_bytes(prng.read(length)) | 1 - base = Integer.from_bytes(prng.read(length)) % modulus2 - exponent2 = Integer.from_bytes(prng.read(length)) - - expected = pow(base, exponent2, modulus2) - result = monty_pow(base, exponent2, modulus2) - self.assertEqual(result, expected) - - def test_variable_exponent(self): - prng = create_rng(b('Test variable exponent')) - for i in range(20): - for j in range(7): - modulus = prng.getrandbits(8*30) | 1 - base = prng.getrandbits(8*30) % modulus - exponent = prng.getrandbits(i*8+j) - - expected = pow(base, exponent, modulus) - result = monty_pow(base, exponent, modulus) - self.assertEqual(result, expected) - - exponent ^= (1 << (i*8+j)) - 1 - - expected = pow(base, exponent, modulus) - result = monty_pow(base, exponent, modulus) - self.assertEqual(result, expected) - - def test_stress_63(self): - prng = create_rng(b('Test 63')) - length = 63 - for _ in range(2000): - modulus = prng.getrandbits(8*length) | 1 - base = prng.getrandbits(8*length) % modulus - exponent = prng.getrandbits(8*length) - - expected = pow(base, exponent, modulus) - result = monty_pow(base, exponent, modulus) - self.assertEqual(result, expected) - - def test_stress_64(self): - prng = create_rng(b('Test 64')) - length = 64 - for _ in range(2000): - modulus = prng.getrandbits(8*length) | 1 - base = prng.getrandbits(8*length) % modulus - exponent = prng.getrandbits(8*length) - - expected = pow(base, exponent, modulus) - result = monty_pow(base, exponent, modulus) - self.assertEqual(result, expected) - - def test_stress_65(self): - prng = create_rng(b('Test 65')) - length = 65 - for _ in range(2000): - modulus = prng.getrandbits(8*length) | 1 - base = prng.getrandbits(8*length) % modulus - exponent = prng.getrandbits(8*length) - - expected = pow(base, exponent, modulus) - result = monty_pow(base, exponent, modulus) - self.assertEqual(result, expected) - - -def get_tests(config={}): - tests = [] - tests += list_test_cases(TestModExp) - return tests - - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/Protocol/__init__.py b/Crypto/SelfTest/Protocol/__init__.py deleted file mode 100644 index 1c1c095..0000000 --- a/Crypto/SelfTest/Protocol/__init__.py +++ /dev/null @@ -1,44 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Protocol/__init__.py: Self-tests for Crypto.Protocol -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-test for Crypto.Protocol""" - -__revision__ = "$Id$" - -def get_tests(config={}): - tests = [] - from Crypto.SelfTest.Protocol import test_rfc1751; tests += test_rfc1751.get_tests(config=config) - from Crypto.SelfTest.Protocol import test_KDF; tests += test_KDF.get_tests(config=config) - - from Crypto.SelfTest.Protocol import test_SecretSharing; - tests += test_SecretSharing.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: diff --git a/Crypto/SelfTest/Protocol/__pycache__/__init__.cpython-36.pyc b/Crypto/SelfTest/Protocol/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index 9f84cf6..0000000 Binary files a/Crypto/SelfTest/Protocol/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Protocol/__pycache__/test_KDF.cpython-36.pyc b/Crypto/SelfTest/Protocol/__pycache__/test_KDF.cpython-36.pyc deleted file mode 100644 index 43eb404..0000000 Binary files a/Crypto/SelfTest/Protocol/__pycache__/test_KDF.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Protocol/__pycache__/test_SecretSharing.cpython-36.pyc b/Crypto/SelfTest/Protocol/__pycache__/test_SecretSharing.cpython-36.pyc deleted file mode 100644 index 6f4fbf0..0000000 Binary files a/Crypto/SelfTest/Protocol/__pycache__/test_SecretSharing.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Protocol/__pycache__/test_rfc1751.cpython-36.pyc b/Crypto/SelfTest/Protocol/__pycache__/test_rfc1751.cpython-36.pyc deleted file mode 100644 index 9a1fb8d..0000000 Binary files a/Crypto/SelfTest/Protocol/__pycache__/test_rfc1751.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Protocol/test_KDF.py b/Crypto/SelfTest/Protocol/test_KDF.py deleted file mode 100644 index b2869f8..0000000 --- a/Crypto/SelfTest/Protocol/test_KDF.py +++ /dev/null @@ -1,732 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Protocol/test_KDF.py: Self-test for key derivation functions -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -import unittest -from binascii import unhexlify - -from Crypto.Util.py3compat import b, bchr - -from Crypto.SelfTest.st_common import list_test_cases -from Crypto.SelfTest.loader import load_test_vectors_wycheproof -from Crypto.Hash import SHA1, HMAC, SHA256, MD5, SHA224, SHA384, SHA512 -from Crypto.Cipher import AES, DES3 - -from Crypto.Protocol.KDF import (PBKDF1, PBKDF2, _S2V, HKDF, scrypt, - bcrypt, bcrypt_check) - -from Crypto.Protocol.KDF import _bcrypt_decode - - -def t2b(t): - if t is None: - return None - t2 = t.replace(" ", "").replace("\n", "") - return unhexlify(b(t2)) - - -class TestVector(object): - pass - - -class PBKDF1_Tests(unittest.TestCase): - - # List of tuples with test data. - # Each tuple is made up by: - # Item #0: a pass phrase - # Item #1: salt (8 bytes encoded in hex) - # Item #2: output key length - # Item #3: iterations to use - # Item #4: expected result (encoded in hex) - _testData = ( - # From http://www.di-mgt.com.au/cryptoKDFs.html#examplespbkdf - ("password", "78578E5A5D63CB06", 16, 1000, "DC19847E05C64D2FAF10EBFB4A3D2A20"), - ) - - def test1(self): - v = self._testData[0] - res = PBKDF1(v[0], t2b(v[1]), v[2], v[3], SHA1) - self.assertEqual(res, t2b(v[4])) - - -class PBKDF2_Tests(unittest.TestCase): - - # List of tuples with test data. - # Each tuple is made up by: - # Item #0: a pass phrase - # Item #1: salt (encoded in hex) - # Item #2: output key length - # Item #3: iterations to use - # Item #4: hash module - # Item #5: expected result (encoded in hex) - _testData = ( - # From http://www.di-mgt.com.au/cryptoKDFs.html#examplespbkdf - ("password","78578E5A5D63CB06",24,2048, SHA1, "BFDE6BE94DF7E11DD409BCE20A0255EC327CB936FFE93643"), - # From RFC 6050 - ("password","73616c74", 20, 1, SHA1, "0c60c80f961f0e71f3a9b524af6012062fe037a6"), - ("password","73616c74", 20, 2, SHA1, "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957"), - ("password","73616c74", 20, 4096, SHA1, "4b007901b765489abead49d926f721d065a429c1"), - ("passwordPASSWORDpassword","73616c7453414c5473616c7453414c5473616c7453414c5473616c7453414c5473616c74", - 25, 4096, SHA1, "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038"), - ( 'pass\x00word',"7361006c74",16,4096, SHA1, "56fa6aa75548099dcc37d7f03425e0c3"), - # From draft-josefsson-scrypt-kdf-01, Chapter 10 - ( 'passwd', '73616c74', 64, 1, SHA256, "55ac046e56e3089fec1691c22544b605f94185216dde0465e68b9d57c20dacbc49ca9cccf179b645991664b39d77ef317c71b845b1e30bd509112041d3a19783"), - ( 'Password', '4e61436c', 64, 80000, SHA256, "4ddcd8f60b98be21830cee5ef22701f9641a4418d04c0414aeff08876b34ab56a1d425a1225833549adb841b51c9b3176a272bdebba1d078478f62b397f33c8d"), - ) - - def test1(self): - # Test only for HMAC-SHA1 as PRF - - def prf_SHA1(p,s): - return HMAC.new(p,s,SHA1).digest() - - def prf_SHA256(p,s): - return HMAC.new(p,s,SHA256).digest() - - for i in range(len(self._testData)): - v = self._testData[i] - password = v[0] - salt = t2b(v[1]) - out_len = v[2] - iters = v[3] - hash_mod = v[4] - expected = t2b(v[5]) - - if hash_mod is SHA1: - res = PBKDF2(password, salt, out_len, iters) - self.assertEqual(res, expected) - - res = PBKDF2(password, salt, out_len, iters, prf_SHA1) - self.assertEqual(res, expected) - else: - res = PBKDF2(password, salt, out_len, iters, prf_SHA256) - self.assertEqual(res, expected) - - def test2(self): - # Verify that prf and hmac_hash_module are mutual exclusive - def prf_SHA1(p,s): - return HMAC.new(p,s,SHA1).digest() - - self.assertRaises(ValueError, PBKDF2, b("xxx"), b("yyy"), 16, 100, - prf=prf_SHA1, hmac_hash_module=SHA1) - - def test3(self): - # Verify that hmac_hash_module works like prf - - password = b("xxx") - salt = b("yyy") - - for hashmod in (MD5, SHA1, SHA224, SHA256, SHA384, SHA512): - - pr1 = PBKDF2(password, salt, 16, 100, - prf=lambda p, s: HMAC.new(p,s,hashmod).digest()) - pr2 = PBKDF2(password, salt, 16, 100, hmac_hash_module=hashmod) - - self.assertEqual(pr1, pr2) - - def test4(self): - # Verify that PBKDF2 can take bytes or strings as password or salt - k1 = PBKDF2("xxx", b("yyy"), 16, 10) - k2 = PBKDF2(b("xxx"), b("yyy"), 16, 10) - self.assertEqual(k1, k2) - - k1 = PBKDF2(b("xxx"), "yyy", 16, 10) - k2 = PBKDF2(b("xxx"), b("yyy"), 16, 10) - self.assertEqual(k1, k2) - - -class S2V_Tests(unittest.TestCase): - - # Sequence of test vectors. - # Each test vector is made up by: - # Item #0: a tuple of strings - # Item #1: an AES key - # Item #2: the result - # Item #3: the cipher module S2V is based on - # Everything is hex encoded - _testData = [ - - # RFC5297, A.1 - ( - ( '101112131415161718191a1b1c1d1e1f2021222324252627', - '112233445566778899aabbccddee' ), - 'fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0', - '85632d07c6e8f37f950acd320a2ecc93', - AES - ), - - # RFC5297, A.2 - ( - ( '00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddcc'+ - 'bbaa99887766554433221100', - '102030405060708090a0', - '09f911029d74e35bd84156c5635688c0', - '7468697320697320736f6d6520706c61'+ - '696e7465787420746f20656e63727970'+ - '74207573696e67205349562d414553'), - '7f7e7d7c7b7a79787776757473727170', - '7bdb6e3b432667eb06f4d14bff2fbd0f', - AES - ), - - ] - - def test1(self): - """Verify correctness of test vector""" - for tv in self._testData: - s2v = _S2V.new(t2b(tv[1]), tv[3]) - for s in tv[0]: - s2v.update(t2b(s)) - result = s2v.derive() - self.assertEqual(result, t2b(tv[2])) - - def test2(self): - """Verify that no more than 127(AES) and 63(TDES) - components are accepted.""" - key = bchr(0) * 8 + bchr(255) * 8 - for module in (AES, DES3): - s2v = _S2V.new(key, module) - max_comps = module.block_size*8-1 - for i in range(max_comps): - s2v.update(b("XX")) - self.assertRaises(TypeError, s2v.update, b("YY")) - - -class HKDF_Tests(unittest.TestCase): - - # Test vectors from RFC5869, Appendix A - # Each tuple is made up by: - # Item #0: hash module - # Item #1: secret - # Item #2: salt - # Item #3: context - # Item #4: expected result - _test_vector = ( - ( - SHA256, - "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", - "000102030405060708090a0b0c", - "f0f1f2f3f4f5f6f7f8f9", - 42, - "3cb25f25faacd57a90434f64d0362f2a" + - "2d2d0a90cf1a5a4c5db02d56ecc4c5bf" + - "34007208d5b887185865" - ), - ( - SHA256, - "000102030405060708090a0b0c0d0e0f" + - "101112131415161718191a1b1c1d1e1f" + - "202122232425262728292a2b2c2d2e2f" + - "303132333435363738393a3b3c3d3e3f" + - "404142434445464748494a4b4c4d4e4f", - "606162636465666768696a6b6c6d6e6f" + - "707172737475767778797a7b7c7d7e7f" + - "808182838485868788898a8b8c8d8e8f" + - "909192939495969798999a9b9c9d9e9f" + - "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", - "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + - "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + - "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + - "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + - "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", - 82, - "b11e398dc80327a1c8e7f78c596a4934" + - "4f012eda2d4efad8a050cc4c19afa97c" + - "59045a99cac7827271cb41c65e590e09" + - "da3275600c2f09b8367793a9aca3db71" + - "cc30c58179ec3e87c14c01d5c1f3434f" + - "1d87" - ), - ( - SHA256, - "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", - None, - None, - 42, - "8da4e775a563c18f715f802a063c5a31" + - "b8a11f5c5ee1879ec3454e5f3c738d2d" + - "9d201395faa4b61a96c8" - ), - ( - SHA1, - "0b0b0b0b0b0b0b0b0b0b0b", - "000102030405060708090a0b0c", - "f0f1f2f3f4f5f6f7f8f9", - 42, - "085a01ea1b10f36933068b56efa5ad81" + - "a4f14b822f5b091568a9cdd4f155fda2" + - "c22e422478d305f3f896" - ), - ( - SHA1, - "000102030405060708090a0b0c0d0e0f" + - "101112131415161718191a1b1c1d1e1f" + - "202122232425262728292a2b2c2d2e2f" + - "303132333435363738393a3b3c3d3e3f" + - "404142434445464748494a4b4c4d4e4f", - "606162636465666768696a6b6c6d6e6f" + - "707172737475767778797a7b7c7d7e7f" + - "808182838485868788898a8b8c8d8e8f" + - "909192939495969798999a9b9c9d9e9f" + - "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", - "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + - "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + - "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + - "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + - "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", - 82, - "0bd770a74d1160f7c9f12cd5912a06eb" + - "ff6adcae899d92191fe4305673ba2ffe" + - "8fa3f1a4e5ad79f3f334b3b202b2173c" + - "486ea37ce3d397ed034c7f9dfeb15c5e" + - "927336d0441f4c4300e2cff0d0900b52" + - "d3b4" - ), - ( - SHA1, - "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", - "", - "", - 42, - "0ac1af7002b3d761d1e55298da9d0506" + - "b9ae52057220a306e07b6b87e8df21d0" + - "ea00033de03984d34918" - ), - ( - SHA1, - "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", - None, - "", - 42, - "2c91117204d745f3500d636a62f64f0a" + - "b3bae548aa53d423b0d1f27ebba6f5e5" + - "673a081d70cce7acfc48" - ) - ) - - def test1(self): - for tv in self._test_vector: - secret, salt, info, exp = [ t2b(tv[x]) for x in (1,2,3,5) ] - key_len, hashmod = [ tv[x] for x in (4,0) ] - - output = HKDF(secret, key_len, salt, hashmod, 1, info) - self.assertEqual(output, exp) - - def test2(self): - ref = HKDF(b("XXXXXX"), 12, b("YYYY"), SHA1) - - # Same output, but this time split over 2 keys - key1, key2 = HKDF(b("XXXXXX"), 6, b("YYYY"), SHA1, 2) - self.assertEqual((ref[:6], ref[6:]), (key1, key2)) - - # Same output, but this time split over 3 keys - key1, key2, key3 = HKDF(b("XXXXXX"), 4, b("YYYY"), SHA1, 3) - self.assertEqual((ref[:4], ref[4:8], ref[8:]), (key1, key2, key3)) - - -class scrypt_Tests(unittest.TestCase): - - # Test vectors taken from - # https://tools.ietf.org/html/rfc7914 - # - password - # - salt - # - N - # - r - # - p - data = ( - ( - "", - "", - 16, # 2K - 1, - 1, - """ - 77 d6 57 62 38 65 7b 20 3b 19 ca 42 c1 8a 04 97 - f1 6b 48 44 e3 07 4a e8 df df fa 3f ed e2 14 42 - fc d0 06 9d ed 09 48 f8 32 6a 75 3a 0f c8 1f 17 - e8 d3 e0 fb 2e 0d 36 28 cf 35 e2 0c 38 d1 89 06 - """ - ), - ( - "password", - "NaCl", - 1024, # 1M - 8, - 16, - """ - fd ba be 1c 9d 34 72 00 78 56 e7 19 0d 01 e9 fe - 7c 6a d7 cb c8 23 78 30 e7 73 76 63 4b 37 31 62 - 2e af 30 d9 2e 22 a3 88 6f f1 09 27 9d 98 30 da - c7 27 af b9 4a 83 ee 6d 83 60 cb df a2 cc 06 40 - """ - ), - ( - "pleaseletmein", - "SodiumChloride", - 16384, # 16M - 8, - 1, - """ - 70 23 bd cb 3a fd 73 48 46 1c 06 cd 81 fd 38 eb - fd a8 fb ba 90 4f 8e 3e a9 b5 43 f6 54 5d a1 f2 - d5 43 29 55 61 3f 0f cf 62 d4 97 05 24 2a 9a f9 - e6 1e 85 dc 0d 65 1e 40 df cf 01 7b 45 57 58 87 - """ - ), - ( - "pleaseletmein", - "SodiumChloride", - 1048576, # 1G - 8, - 1, - """ - 21 01 cb 9b 6a 51 1a ae ad db be 09 cf 70 f8 81 - ec 56 8d 57 4a 2f fd 4d ab e5 ee 98 20 ad aa 47 - 8e 56 fd 8f 4b a5 d0 9f fa 1c 6d 92 7c 40 f4 c3 - 37 30 40 49 e8 a9 52 fb cb f4 5c 6f a7 7a 41 a4 - """ - ), - ) - - def setUp(self): - new_test_vectors = [] - for tv in self.data: - new_tv = TestVector() - new_tv.P = b(tv[0]) - new_tv.S = b(tv[1]) - new_tv.N = tv[2] - new_tv.r = tv[3] - new_tv.p = tv[4] - new_tv.output = t2b(tv[5]) - new_tv.dkLen = len(new_tv.output) - new_test_vectors.append(new_tv) - self.data = new_test_vectors - - def test2(self): - - for tv in self.data: - try: - output = scrypt(tv.P, tv.S, tv.dkLen, tv.N, tv.r, tv.p) - except ValueError as e: - if " 2 " in str(e) and tv.N >= 1048576: - import warnings - warnings.warn("Not enough memory to unit test scrypt() with N=1048576", RuntimeWarning) - continue - else: - raise e - self.assertEqual(output, tv.output) - - def test3(self): - ref = scrypt(b("password"), b("salt"), 12, 16, 1, 1) - - # Same output, but this time split over 2 keys - key1, key2 = scrypt(b("password"), b("salt"), 6, 16, 1, 1, 2) - self.assertEqual((ref[:6], ref[6:]), (key1, key2)) - - # Same output, but this time split over 3 keys - key1, key2, key3 = scrypt(b("password"), b("salt"), 4, 16, 1, 1, 3) - self.assertEqual((ref[:4], ref[4:8], ref[8:]), (key1, key2, key3)) - - -class bcrypt_Tests(unittest.TestCase): - - def test_negative_cases(self): - self.assertRaises(ValueError, bcrypt, b"1" * 73, 10) - self.assertRaises(ValueError, bcrypt, b"1" * 10, 3) - self.assertRaises(ValueError, bcrypt, b"1" * 10, 32) - self.assertRaises(ValueError, bcrypt, b"1" * 10, 4, salt=b"") - self.assertRaises(ValueError, bcrypt, b"1" * 10, 4, salt=b"1") - self.assertRaises(ValueError, bcrypt, b"1" * 10, 4, salt=b"1" * 17) - self.assertRaises(ValueError, bcrypt, b"1\x00" * 10, 4) - - def test_bytearray_mismatch(self): - ref = bcrypt("pwd", 4) - bcrypt_check("pwd", ref) - bref = bytearray(ref) - bcrypt_check("pwd", bref) - - wrong = ref[:-1] + bchr(bref[-1] ^ 0x01) - self.assertRaises(ValueError, bcrypt_check, "pwd", wrong) - - wrong = b"x" + ref[1:] - self.assertRaises(ValueError, bcrypt_check, "pwd", wrong) - - # https://github.com/patrickfav/bcrypt/wiki/Published-Test-Vectors - - def test_empty_password(self): - # password, cost, salt, bcrypt hash - tvs = [ - (b"", 4, b"zVHmKQtGGQob.b/Nc7l9NO", b"$2a$04$zVHmKQtGGQob.b/Nc7l9NO8UlrYcW05FiuCj/SxsFO/ZtiN9.mNzy"), - (b"", 5, b"zVHmKQtGGQob.b/Nc7l9NO", b"$2a$05$zVHmKQtGGQob.b/Nc7l9NOWES.1hkVBgy5IWImh9DOjKNU8atY4Iy"), - (b"", 6, b"zVHmKQtGGQob.b/Nc7l9NO", b"$2a$06$zVHmKQtGGQob.b/Nc7l9NOjOl7l4oz3WSh5fJ6414Uw8IXRAUoiaO"), - (b"", 7, b"zVHmKQtGGQob.b/Nc7l9NO", b"$2a$07$zVHmKQtGGQob.b/Nc7l9NOBsj1dQpBA1HYNGpIETIByoNX9jc.hOi"), - (b"", 8, b"zVHmKQtGGQob.b/Nc7l9NO", b"$2a$08$zVHmKQtGGQob.b/Nc7l9NOiLTUh/9MDpX86/DLyEzyiFjqjBFePgO"), - ] - - for (idx, (password, cost, salt64, result)) in enumerate(tvs): - x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) - self.assertEqual(x, result) - bcrypt_check(password, result) - - def test_random_password_and_salt_short_pw(self): - # password, cost, salt, bcrypt hash - tvs = [ - (b"<.S.2K(Zq'", 4, b"VYAclAMpaXY/oqAo9yUpku", b"$2a$04$VYAclAMpaXY/oqAo9yUpkuWmoYywaPzyhu56HxXpVltnBIfmO9tgu"), - (b"5.rApO%5jA", 5, b"kVNDrnYKvbNr5AIcxNzeIu", b"$2a$05$kVNDrnYKvbNr5AIcxNzeIuRcyIF5cZk6UrwHGxENbxP5dVv.WQM/G"), - (b"oW++kSrQW^", 6, b"QLKkRMH9Am6irtPeSKN5sO", b"$2a$06$QLKkRMH9Am6irtPeSKN5sObJGr3j47cO6Pdf5JZ0AsJXuze0IbsNm"), - (b"ggJ\\KbTnDG", 7, b"4H896R09bzjhapgCPS/LYu", b"$2a$07$4H896R09bzjhapgCPS/LYuMzAQluVgR5iu/ALF8L8Aln6lzzYXwbq"), - (b"49b0:;VkH/", 8, b"hfvO2retKrSrx5f2RXikWe", b"$2a$08$hfvO2retKrSrx5f2RXikWeFWdtSesPlbj08t/uXxCeZoHRWDz/xFe"), - (b">9N^5jc##'", 9, b"XZLvl7rMB3EvM0c1.JHivu", b"$2a$09$XZLvl7rMB3EvM0c1.JHivuIDPJWeNJPTVrpjZIEVRYYB/mF6cYgJK"), - (b"\\$ch)s4WXp", 10, b"aIjpMOLK5qiS9zjhcHR5TO", b"$2a$10$aIjpMOLK5qiS9zjhcHR5TOU7v2NFDmcsBmSFDt5EHOgp/jeTF3O/q"), - (b"RYoj\\_>2P7", 12, b"esIAHiQAJNNBrsr5V13l7.", b"$2a$12$esIAHiQAJNNBrsr5V13l7.RFWWJI2BZFtQlkFyiWXjou05GyuREZa"), - ] - - for (idx, (password, cost, salt64, result)) in enumerate(tvs): - x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) - self.assertEqual(x, result) - bcrypt_check(password, result) - - def test_random_password_and_salt_long_pw(self): - # password, cost, salt, bcrypt hash - tvs = [ - (b"^Q&\"]A`%/A(BVGt>QaX0M-#1ghq_+\":Y0CRmY", 5, b"YuQvhokOGVnevctykUYpKu", b"$2a$05$YuQvhokOGVnevctykUYpKutZD2pWeGGYn3auyLOasguMY3/0BbIyq"), - (b"F%uN/j>[GuB7-jB'_Yj!Tnb7Y!u^6)", 6, b"5L3vpQ0tG9O7k5gQ8nAHAe", b"$2a$06$5L3vpQ0tG9O7k5gQ8nAHAe9xxQiOcOLh8LGcI0PLWhIznsDt.S.C6"), - (b"Z>BobP32ub\"Cfe*Q<-q-=tRSjOBh8\\mLNW.", 9, b"nArqOfdCsD9kIbVnAixnwe", b"$2a$09$nArqOfdCsD9kIbVnAixnwe6s8QvyPYWtQBpEXKir2OJF9/oNBsEFe"), - (b"/MH51`!BP&0tj3%YCA;Xk%e3S`o\\EI", 10, b"ePiAc.s.yoBi3B6p1iQUCe", b"$2a$10$ePiAc.s.yoBi3B6p1iQUCezn3mraLwpVJ5XGelVyYFKyp5FZn/y.u"), - (b"ptAP\"mcg6oH.\";c0U2_oll.OKi5?Ui\"^ai#iQH7ZFtNMfs3AROnIncE9\"BNNoEgO[[*Yk8;RQ(#S,;I+aT", - 5, b"wgkOlGNXIVE2fWkT3gyRoO", b"$2a$05$wgkOlGNXIVE2fWkT3gyRoOqWi4gbi1Wv2Q2Jx3xVs3apl1w.Wtj8C"), - (b"M.E1=dt<.L0Q&p;94NfGm_Oo23+Kpl@M5?WIAL.[@/:'S)W96G8N^AWb7_smmC]>7#fGoB", - 6, b"W9zTCl35nEvUukhhFzkKMe", b"$2a$06$W9zTCl35nEvUukhhFzkKMekjT9/pj7M0lihRVEZrX3m8/SBNZRX7i"), - ] - - for (idx, (password, cost, salt64, result)) in enumerate(tvs): - x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) - self.assertEqual(x, result) - bcrypt_check(password, result) - - def test_increasing_password_length(self): - # password, cost, salt, bcrypt hash - tvs = [ - (b"a", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.l4WvgHIVg17ZawDIrDM2IjlE64GDNQS"), - (b"aa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.AyUxBk.ThHlsLvRTH7IqcG7yVHJ3SXq"), - (b"aaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.BxOVac5xPB6XFdRc/ZrzM9FgZkqmvbW"), - (b"aaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.Qbr209bpCtfl5hN7UQlG/L4xiD3AKau"), - (b"aaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.oWszihPjDZI0ypReKsaDOW1jBl7oOii"), - (b"aaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ./k.Xxn9YiqtV/sxh3EHbnOHd0Qsq27K"), - (b"aaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.PYJqRFQbgRbIjMd5VNKmdKS4sBVOyDe"), - (b"aaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ..VMYfzaw1wP/SGxowpLeGf13fxCCt.q"), - (b"aaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.5B0p054nO5WgAD1n04XslDY/bqY9RJi"), - (b"aaaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.INBTgqm7sdlBJDg.J5mLMSRK25ri04y"), - (b"aaaaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.s3y7CdFD0OR5p6rsZw/eZ.Dla40KLfm"), - (b"aaaaaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.Jx742Djra6Q7PqJWnTAS.85c28g.Siq"), - (b"aaaaaaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.oKMXW3EZcPHcUV0ib5vDBnh9HojXnLu"), - (b"aaaaaaaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.w6nIjWpDPNSH5pZUvLjC1q25ONEQpeS"), - (b"aaaaaaaaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.k1b2/r9A/hxdwKEKurg6OCn4MwMdiGq"), - (b"aaaaaaaaaaaaaaaa", 4, b"5DCebwootqWMCp59ISrMJ.", b"$2a$04$5DCebwootqWMCp59ISrMJ.3prCNHVX1Ws.7Hm2bJxFUnQOX9f7DFa"), - ] - - for (idx, (password, cost, salt64, result)) in enumerate(tvs): - x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) - self.assertEqual(x, result) - bcrypt_check(password, result) - - def test_non_ascii_characters(self): - # password, cost, salt, bcrypt hash - tvs = [ - ("àèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝðÐ", 4, b"D3qS2aoTVyqM7z8v8crLm.", b"$2a$04$D3qS2aoTVyqM7z8v8crLm.3nKt4CzBZJbyFB.ZebmfCvRw7BGs.Xm"), - ("àèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝðÐ", 5, b"VA1FujiOCMPkUHQ8kF7IaO", b"$2a$05$VA1FujiOCMPkUHQ8kF7IaOg7NGaNvpxwWzSluQutxEVmbZItRTsAa"), - ("àèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝðÐ", 6, b"TXiaNrPeBSz5ugiQlehRt.", b"$2a$06$TXiaNrPeBSz5ugiQlehRt.gwpeDQnXWteQL4z2FulouBr6G7D9KUi"), - ("âêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿ", 4, b"YTn1Qlvps8e1odqMn6G5x.", b"$2a$04$YTn1Qlvps8e1odqMn6G5x.85pqKql6w773EZJAExk7/BatYAI4tyO"), - ("âêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿ", 5, b"C.8k5vJKD2NtfrRI9o17DO", b"$2a$05$C.8k5vJKD2NtfrRI9o17DOfIW0XnwItA529vJnh2jzYTb1QdoY0py"), - ("âêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿ", 6, b"xqfRPj3RYAgwurrhcA6uRO", b"$2a$06$xqfRPj3RYAgwurrhcA6uROtGlXDp/U6/gkoDYHwlubtcVcNft5.vW"), - ("ÄËÏÖÜŸåÅæÆœŒßçÇøØ¢¿¡€", 4, b"y8vGgMmr9EdyxP9rmMKjH.", b"$2a$04$y8vGgMmr9EdyxP9rmMKjH.wv2y3r7yRD79gykQtmb3N3zrwjKsyay"), - ("ÄËÏÖÜŸåÅæÆœŒßçÇøØ¢¿¡€", 5, b"iYH4XIKAOOm/xPQs7xKP1u", b"$2a$05$iYH4XIKAOOm/xPQs7xKP1upD0cWyMn3Jf0ZWiizXbEkVpS41K1dcO"), - ("ÄËÏÖÜŸåÅæÆœŒßçÇøØ¢¿¡€", 6, b"wCOob.D0VV8twafNDB2ape", b"$2a$06$wCOob.D0VV8twafNDB2apegiGD5nqF6Y1e6K95q6Y.R8C4QGd265q"), - ("ΔημοσιεύθηκεστηνΕφημερίδατης", 4, b"E5SQtS6P4568MDXW7cyUp.", b"$2a$04$E5SQtS6P4568MDXW7cyUp.18wfDisKZBxifnPZjAI1d/KTYMfHPYO"), - ("АБбВвГгДдЕеЁёЖжЗзИиЙйКкЛлМмН", 4, b"03e26gQFHhQwRNf81/ww9.", b"$2a$04$03e26gQFHhQwRNf81/ww9.p1UbrNwxpzWjLuT.zpTLH4t/w5WhAhC"), - ("нОоПпРрСсТтУуФфХхЦцЧчШшЩщЪъЫыЬьЭэЮю", 4, b"PHNoJwpXCfe32nUtLv2Upu", b"$2a$04$PHNoJwpXCfe32nUtLv2UpuhJXOzd4k7IdFwnEpYwfJVCZ/f/.8Pje"), - ("電电電島岛島兔兔兎龜龟亀國国国區区区", 4, b"wU4/0i1TmNl2u.1jIwBX.u", b"$2a$04$wU4/0i1TmNl2u.1jIwBX.uZUaOL3Rc5ID7nlQRloQh6q5wwhV/zLW"), - ("诶比伊艾弗豆贝尔维吾艾尺开艾丝维贼德", 4, b"P4kreGLhCd26d4WIy7DJXu", b"$2a$04$P4kreGLhCd26d4WIy7DJXusPkhxLvBouzV6OXkL5EB0jux0osjsry"), - ] - - for (idx, (password, cost, salt64, result)) in enumerate(tvs): - x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) - self.assertEqual(x, result) - bcrypt_check(password, result) - - def test_special_case_salt(self): - # password, cost, salt, bcrypt hash - tvs = [ - ("-O_=*N!2JP", 4, b"......................", b"$2a$04$......................JjuKLOX9OOwo5PceZZXSkaLDvdmgb82"), - ("7B[$Q<4b>U", 5, b"......................", b"$2a$05$......................DRiedDQZRL3xq5A5FL8y7/6NM8a2Y5W"), - (">d5-I_8^.h", 6, b"......................", b"$2a$06$......................5Mq1Ng8jgDY.uHNU4h5p/x6BedzNH2W"), - (")V`/UM/]1t", 4, b".OC/.OC/.OC/.OC/.OC/.O", b"$2a$04$.OC/.OC/.OC/.OC/.OC/.OQIvKRDAam.Hm5/IaV/.hc7P8gwwIbmi"), - (":@t2.bWuH]", 5, b".OC/.OC/.OC/.OC/.OC/.O", b"$2a$05$.OC/.OC/.OC/.OC/.OC/.ONDbUvdOchUiKmQORX6BlkPofa/QxW9e"), - ("b(#KljF5s\"", 6, b".OC/.OC/.OC/.OC/.OC/.O", b"$2a$06$.OC/.OC/.OC/.OC/.OC/.OHfTd9e7svOu34vi1PCvOcAEq07ST7.K"), - ("@3YaJ^Xs]*", 4, b"eGA.eGA.eGA.eGA.eGA.e.", b"$2a$04$eGA.eGA.eGA.eGA.eGA.e.stcmvh.R70m.0jbfSFVxlONdj1iws0C"), - ("'\"5\\!k*C(p", 5, b"eGA.eGA.eGA.eGA.eGA.e.", b"$2a$05$eGA.eGA.eGA.eGA.eGA.e.vR37mVSbfdHwu.F0sNMvgn8oruQRghy"), - ("edEu7C?$'W", 6, b"eGA.eGA.eGA.eGA.eGA.e.", b"$2a$06$eGA.eGA.eGA.eGA.eGA.e.tSq0FN8MWHQXJXNFnHTPQKtA.n2a..G"), - ("N7dHmg\\PI^", 4, b"999999999999999999999u", b"$2a$04$999999999999999999999uCZfA/pLrlyngNDMq89r1uUk.bQ9icOu"), - ("\"eJuHh!)7*", 5, b"999999999999999999999u", b"$2a$05$999999999999999999999uj8Pfx.ufrJFAoWFLjapYBS5vVEQQ/hK"), - ("ZeDRJ:_tu:", 6, b"999999999999999999999u", b"$2a$06$999999999999999999999u6RB0P9UmbdbQgjoQFEJsrvrKe.BoU6q"), - ] - - for (idx, (password, cost, salt64, result)) in enumerate(tvs): - x = bcrypt(password, cost, salt=_bcrypt_decode(salt64)) - self.assertEqual(x, result) - bcrypt_check(password, result) - - -class TestVectorsHKDFWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._id = "None" - - def add_tests(self, filename): - - def filter_algo(root): - algo_name = root['algorithm'] - if algo_name == "HKDF-SHA-1": - return SHA1 - elif algo_name == "HKDF-SHA-256": - return SHA256 - elif algo_name == "HKDF-SHA-384": - return SHA384 - elif algo_name == "HKDF-SHA-512": - return SHA512 - else: - raise ValueError("Unknown algorithm " + algo_name) - - def filter_size(unit): - return int(unit['size']) - - result = load_test_vectors_wycheproof(("Protocol", "wycheproof"), - filename, - "Wycheproof HMAC (%s)" % filename, - root_tag={'hash_module': filter_algo}, - unit_tag={'size': filter_size}) - return result - - def setUp(self): - self.tv = [] - self.add_tests("hkdf_sha1_test.json") - self.add_tests("hkdf_sha256_test.json") - self.add_tests("hkdf_sha384_test.json") - self.add_tests("hkdf_sha512_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_verify(self, tv): - self._id = "Wycheproof HKDF Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) - - try: - key = HKDF(tv.ikm, tv.size, tv.salt, tv.hash_module, 1, tv.info) - except ValueError: - assert not tv.valid - else: - if key != tv.okm: - assert not tv.valid - else: - assert tv.valid - self.warn(tv) - - def runTest(self): - for tv in self.tv: - self.test_verify(tv) - - -def get_tests(config={}): - wycheproof_warnings = config.get('wycheproof_warnings') - - if not config.get('slow_tests'): - PBKDF2_Tests._testData = PBKDF2_Tests._testData[:3] - scrypt_Tests.data = scrypt_Tests.data[:3] - - tests = [] - tests += list_test_cases(PBKDF1_Tests) - tests += list_test_cases(PBKDF2_Tests) - tests += list_test_cases(S2V_Tests) - tests += list_test_cases(HKDF_Tests) - tests += [TestVectorsHKDFWycheproof(wycheproof_warnings)] - tests += list_test_cases(scrypt_Tests) - tests += list_test_cases(bcrypt_Tests) - - return tests - - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/Protocol/test_SecretSharing.py b/Crypto/SelfTest/Protocol/test_SecretSharing.py deleted file mode 100644 index 368d3c0..0000000 --- a/Crypto/SelfTest/Protocol/test_SecretSharing.py +++ /dev/null @@ -1,267 +0,0 @@ -# -# SelfTest/Protocol/test_secret_sharing.py: Self-test for secret sharing protocols -# -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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 unittest import main, TestCase, TestSuite -from binascii import unhexlify, hexlify - -from Crypto.Util.py3compat import * -from Crypto.SelfTest.st_common import list_test_cases - -from Crypto.Protocol.SecretSharing import Shamir, _Element, \ - _mult_gf2, _div_gf2 - -class GF2_Tests(TestCase): - - def test_mult_gf2(self): - # Prove mult by zero - x = _mult_gf2(0,0) - self.assertEqual(x, 0) - - # Prove mult by unity - x = _mult_gf2(34, 1) - self.assertEqual(x, 34) - - z = 3 # (x+1) - y = _mult_gf2(z, z) - self.assertEqual(y, 5) # (x+1)^2 = x^2 + 1 - y = _mult_gf2(y, z) - self.assertEqual(y, 15) # (x+1)^3 = x^3 + x^2 + x + 1 - y = _mult_gf2(y, z) - self.assertEqual(y, 17) # (x+1)^4 = x^4 + 1 - - # Prove linearity works - comps = [1, 4, 128, 2**34] - sum_comps = 1+4+128+2**34 - y = 908 - z = _mult_gf2(sum_comps, y) - w = 0 - for x in comps: - w ^= _mult_gf2(x, y) - self.assertEqual(w, z) - - def test_div_gf2(self): - from Crypto.Util.number import size as deg - - x, y = _div_gf2(567, 7) - self.failUnless(deg(y) < deg(7)) - - w = _mult_gf2(x, 7) ^ y - self.assertEqual(567, w) - - x, y = _div_gf2(7, 567) - self.assertEqual(x, 0) - self.assertEqual(y, 7) - -class Element_Tests(TestCase): - - def test1(self): - # Test encondings - e = _Element(256) - self.assertEqual(int(e), 256) - self.assertEqual(e.encode(), bchr(0)*14 + b("\x01\x00")) - - e = _Element(bchr(0)*14 + b("\x01\x10")) - self.assertEqual(int(e), 0x110) - self.assertEqual(e.encode(), bchr(0)*14 + b("\x01\x10")) - - # Only 16 byte string are a valid encoding - self.assertRaises(ValueError, _Element, bchr(0)) - - def test2(self): - # Test addition - e = _Element(0x10) - f = _Element(0x0A) - self.assertEqual(int(e+f), 0x1A) - - def test3(self): - # Test multiplication - zero = _Element(0) - one = _Element(1) - two = _Element(2) - - x = _Element(6) * zero - self.assertEqual(int(x), 0) - - x = _Element(6) * one - self.assertEqual(int(x), 6) - - x = _Element(2**127) * two - self.assertEqual(int(x), 1 + 2 + 4 + 128) - - def test4(self): - # Test inversion - one = _Element(1) - - x = one.inverse() - self.assertEqual(int(x), 1) - - x = _Element(82323923) - y = x.inverse() - self.assertEqual(int(x * y), 1) - -class Shamir_Tests(TestCase): - - def test1(self): - # Test splitting - shares = Shamir.split(2, 3, bchr(90)*16) - self.assertEqual(len(shares), 3) - for index in range(3): - self.assertEqual(shares[index][0], index+1) - self.assertEqual(len(shares[index][1]), 16) - - def test2(self): - # Test recombine - from itertools import permutations - - test_vectors = ( - (2, "d9fe73909bae28b3757854c0af7ad405", - "1-594ae8964294174d95c33756d2504170", - "2-d897459d29da574eb40e93ec552ffe6e", - "3-5823de9bf0e068b054b5f07a28056b1b", - "4-db2c1f8bff46d748f795da995bd080cb"), - (2, "bf4f902d9a7efafd1f3ffd9291fd5de9", - "1-557bd3b0748064b533469722d1cc7935", - "2-6b2717164783c66d47cd28f2119f14d0", - "3-8113548ba97d58256bb4424251ae300c", - "4-179e9e5a218483ddaeda57539139cf04"), - (3, "ec96aa5c14c9faa699354cf1da74e904", - "1-64579fbf1908d66f7239bf6e2b4e41e1", - "2-6cd9428df8017b52322561e8c672ae3e", - "3-e418776ef5c0579bd9299277374806dd", - "4-ab3f77a0107398d23b323e581bb43f5d", - "5-23fe42431db2b41bd03ecdc7ea8e97ac"), - (3, "44cf249b68b80fcdc27b47be60c2c145", - "1-d6515a3905cd755119b86e311c801e31", - "2-16693d9ac9f10c254036ced5f8917fa3", - "3-84f74338a48476b99bf5e75a84d3a0d1", - "4-3fe8878dc4a5d35811cf3cbcd33dbe52", - "5-ad76f92fa9d0a9c4ca0c1533af7f6132"), - (5, "5398717c982db935d968eebe53a47f5a", - "1-be7be2dd4c068e7ef576aaa1b1c11b01", - "2-f821f5848441cb98b3eb467e2733ee21", - "3-25ee52f53e203f6e29a0297b5ab486b5", - "4-fc9fb58ef74dab947fbf9acd9d5d83cd", - "5-b1949cce46d81552e65f248d3f74cc5c", - "6-d64797f59977c4d4a7956ad916da7699", - "7-ab608a6546a8b9af8820ff832b1135c7"), - (5, "4a78db90fbf35da5545d2fb728e87596", - "1-08daf9a25d8aa184cfbf02b30a0ed6a0", - "2-dda28261e36f0b14168c2cf153fb734e", - "3-e9fdec5505d674a57f9836c417c1ecaa", - "4-4dce5636ae06dee42d2c82e65f06c735", - "5-3963dc118afc2ba798fa1d452b28ef00", - "6-6dfe6ff5b09e94d2f84c382b12f42424", - "7-6faea9d4d4a4e201bf6c90b9000630c3"), - (10, "eccbf6d66d680b49b073c4f1ddf804aa", - "01-7d8ac32fe4ae209ead1f3220fda34466", - "02-f9144e76988aad647d2e61353a6e96d5", - "03-b14c3b80179203363922d60760271c98", - "04-770bb2a8c28f6cee89e00f4d5cc7f861", - "05-6e3d7073ea368334ef67467871c66799", - "06-248792bc74a98ce024477c13c8fb5f8d", - "07-fcea4640d2db820c0604851e293d2487", - "08-2776c36fb714bb1f8525a0be36fc7dba", - "09-6ee7ac8be773e473a4bf75ee5f065762", - "10-33657fc073354cf91d4a68c735aacfc8", - "11-7645c65094a5868bf225c516fdee2d0c", - "12-840485aacb8226631ecd9c70e3018086"), - (10, "377e63bdbb5f7d4dc58a483d035212bb", - "01-32c53260103be431c843b1a633afe3bd", - "02-0107eb16cb8695084d452d2cc50bc7d6", - "03-df1e5c66cd755287fb0446faccd72a06", - "04-361bbcd5d40797f49dfa1898652da197", - "05-160d3ad1512f7dec7fd9344aed318591", - "06-659af6d95df4f25beca4fb9bfee3b7e8", - "07-37f3b208977bad50b3724566b72bfa9d", - "08-6c1de2dfc69c2986142c26a8248eb316", - "09-5e19220837a396bd4bc8cd685ff314c3", - "10-86e7b864fb0f3d628e46d50c1ba92f1c", - "11-065d0082c80b1aea18f4abe0c49df72e", - "12-84a09430c1d20ea9f388f3123c3733a3"), - ) - - def get_share(p): - pos = p.find('-') - return int(p[:pos]), unhexlify(p[pos + 1:]) - - for tv in test_vectors: - k = tv[0] - secret = unhexlify(tv[1]) - max_perms = 10 - for perm, shares_idx in enumerate(permutations(range(2, len(tv)), k)): - if perm > max_perms: - break - shares = [ get_share(tv[x]) for x in shares_idx ] - result = Shamir.combine(shares, True) - self.assertEqual(secret, result) - - def test3(self): - # Loopback split/recombine - secret = unhexlify(b("000102030405060708090a0b0c0d0e0f")) - - shares = Shamir.split(2, 3, secret) - - secret2 = Shamir.combine(shares[:2]) - self.assertEqual(secret, secret2) - - secret3 = Shamir.combine([ shares[0], shares[2] ]) - self.assertEqual(secret, secret3) - - def test4(self): - # Loopback split/recombine (SSSS) - secret = unhexlify(b("000102030405060708090a0b0c0d0e0f")) - - shares = Shamir.split(2, 3, secret, ssss=True) - - secret2 = Shamir.combine(shares[:2], ssss=True) - self.assertEqual(secret, secret2) - - def test5(self): - # Detect duplicate shares - secret = unhexlify(b("000102030405060708090a0b0c0d0e0f")) - - shares = Shamir.split(2, 3, secret) - self.assertRaises(ValueError, Shamir.combine, (shares[0], shares[0])) - - -def get_tests(config={}): - tests = [] - tests += list_test_cases(GF2_Tests) - tests += list_test_cases(Element_Tests) - tests += list_test_cases(Shamir_Tests) - return tests - -if __name__ == '__main__': - suite = lambda: TestSuite(get_tests()) - main(defaultTest='suite') - diff --git a/Crypto/SelfTest/Protocol/test_rfc1751.py b/Crypto/SelfTest/Protocol/test_rfc1751.py deleted file mode 100644 index 0878cc5..0000000 --- a/Crypto/SelfTest/Protocol/test_rfc1751.py +++ /dev/null @@ -1,62 +0,0 @@ -# -# Test script for Crypto.Util.RFC1751. -# -# Part of the Python Cryptography Toolkit -# -# Written by Andrew Kuchling and others -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -__revision__ = "$Id$" - -import binascii -import unittest -from Crypto.Util import RFC1751 -from Crypto.Util.py3compat import * - -test_data = [('EB33F77EE73D4053', 'TIDE ITCH SLOW REIN RULE MOT'), - ('CCAC2AED591056BE4F90FD441C534766', - 'RASH BUSH MILK LOOK BAD BRIM AVID GAFF BAIT ROT POD LOVE'), - ('EFF81F9BFBC65350920CDD7416DE8009', - 'TROD MUTE TAIL WARM CHAR KONG HAAG CITY BORE O TEAL AWL') - ] - -class RFC1751Test_k2e (unittest.TestCase): - - def runTest (self): - "Check converting keys to English" - for key, words in test_data: - key=binascii.a2b_hex(b(key)) - self.assertEqual(RFC1751.key_to_english(key), words) - -class RFC1751Test_e2k (unittest.TestCase): - - def runTest (self): - "Check converting English strings to keys" - for key, words in test_data: - key=binascii.a2b_hex(b(key)) - self.assertEqual(RFC1751.english_to_key(words), key) - -# class RFC1751Test - -def get_tests(config={}): - return [RFC1751Test_k2e(), RFC1751Test_e2k()] - -if __name__ == "__main__": - unittest.main() diff --git a/Crypto/SelfTest/PublicKey/__init__.py b/Crypto/SelfTest/PublicKey/__init__.py deleted file mode 100644 index d4f51bc..0000000 --- a/Crypto/SelfTest/PublicKey/__init__.py +++ /dev/null @@ -1,54 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/PublicKey/__init__.py: Self-test for public key crypto -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-test for public-key crypto""" - -__revision__ = "$Id$" - -import os - -def get_tests(config={}): - tests = [] - from Crypto.SelfTest.PublicKey import test_DSA; tests += test_DSA.get_tests(config=config) - from Crypto.SelfTest.PublicKey import test_RSA; tests += test_RSA.get_tests(config=config) - from Crypto.SelfTest.PublicKey import test_ECC; tests += test_ECC.get_tests(config=config) - - from Crypto.SelfTest.PublicKey import test_import_DSA - tests +=test_import_DSA.get_tests(config=config) - - from Crypto.SelfTest.PublicKey import test_import_RSA - tests += test_import_RSA.get_tests(config=config) - - from Crypto.SelfTest.PublicKey import test_import_ECC - tests += test_import_ECC.get_tests(config=config) - - from Crypto.SelfTest.PublicKey import test_ElGamal; tests += test_ElGamal.get_tests(config=config) - return tests - -if __name__ == '__main__': - import unittest - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') - -# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/Crypto/SelfTest/PublicKey/__pycache__/__init__.cpython-36.pyc b/Crypto/SelfTest/PublicKey/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index 444d993..0000000 Binary files a/Crypto/SelfTest/PublicKey/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/PublicKey/__pycache__/test_DSA.cpython-36.pyc b/Crypto/SelfTest/PublicKey/__pycache__/test_DSA.cpython-36.pyc deleted file mode 100644 index 5df34d6..0000000 Binary files a/Crypto/SelfTest/PublicKey/__pycache__/test_DSA.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/PublicKey/__pycache__/test_ECC.cpython-36.pyc b/Crypto/SelfTest/PublicKey/__pycache__/test_ECC.cpython-36.pyc deleted file mode 100644 index 5549fe2..0000000 Binary files a/Crypto/SelfTest/PublicKey/__pycache__/test_ECC.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/PublicKey/__pycache__/test_ElGamal.cpython-36.pyc b/Crypto/SelfTest/PublicKey/__pycache__/test_ElGamal.cpython-36.pyc deleted file mode 100644 index 06dbbe6..0000000 Binary files a/Crypto/SelfTest/PublicKey/__pycache__/test_ElGamal.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/PublicKey/__pycache__/test_RSA.cpython-36.pyc b/Crypto/SelfTest/PublicKey/__pycache__/test_RSA.cpython-36.pyc deleted file mode 100644 index 223d38e..0000000 Binary files a/Crypto/SelfTest/PublicKey/__pycache__/test_RSA.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/PublicKey/__pycache__/test_import_DSA.cpython-36.pyc b/Crypto/SelfTest/PublicKey/__pycache__/test_import_DSA.cpython-36.pyc deleted file mode 100644 index b51f108..0000000 Binary files a/Crypto/SelfTest/PublicKey/__pycache__/test_import_DSA.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/PublicKey/__pycache__/test_import_ECC.cpython-36.pyc b/Crypto/SelfTest/PublicKey/__pycache__/test_import_ECC.cpython-36.pyc deleted file mode 100644 index 8020cf9..0000000 Binary files a/Crypto/SelfTest/PublicKey/__pycache__/test_import_ECC.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/PublicKey/__pycache__/test_import_RSA.cpython-36.pyc b/Crypto/SelfTest/PublicKey/__pycache__/test_import_RSA.cpython-36.pyc deleted file mode 100644 index d3be72f..0000000 Binary files a/Crypto/SelfTest/PublicKey/__pycache__/test_import_RSA.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/PublicKey/test_DSA.py b/Crypto/SelfTest/PublicKey/test_DSA.py deleted file mode 100644 index 0249de9..0000000 --- a/Crypto/SelfTest/PublicKey/test_DSA.py +++ /dev/null @@ -1,247 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/PublicKey/test_DSA.py: Self-test for the DSA primitive -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-test suite for Crypto.PublicKey.DSA""" - -import os -from Crypto.Util.py3compat import * - -import unittest -from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex - -def _sws(s): - """Remove whitespace from a text or byte string""" - if isinstance(s,str): - return "".join(s.split()) - else: - return b("").join(s.split()) - -class DSATest(unittest.TestCase): - # Test vector from "Appendix 5. Example of the DSA" of - # "Digital Signature Standard (DSS)", - # U.S. Department of Commerce/National Institute of Standards and Technology - # FIPS 186-2 (+Change Notice), 2000 January 27. - # http://csrc.nist.gov/publications/fips/fips186-2/fips186-2-change1.pdf - - y = _sws("""19131871 d75b1612 a819f29d 78d1b0d7 346f7aa7 7bb62a85 - 9bfd6c56 75da9d21 2d3a36ef 1672ef66 0b8c7c25 5cc0ec74 - 858fba33 f44c0669 9630a76b 030ee333""") - - g = _sws("""626d0278 39ea0a13 413163a5 5b4cb500 299d5522 956cefcb - 3bff10f3 99ce2c2e 71cb9de5 fa24babf 58e5b795 21925c9c - c42e9f6f 464b088c c572af53 e6d78802""") - - p = _sws("""8df2a494 492276aa 3d25759b b06869cb eac0d83a fb8d0cf7 - cbb8324f 0d7882e5 d0762fc5 b7210eaf c2e9adac 32ab7aac - 49693dfb f83724c2 ec0736ee 31c80291""") - - q = _sws("""c773218c 737ec8ee 993b4f2d ed30f48e dace915f""") - - x = _sws("""2070b322 3dba372f de1c0ffc 7b2e3b49 8b260614""") - - k = _sws("""358dad57 1462710f 50e254cf 1a376b2b deaadfbf""") - k_inverse = _sws("""0d516729 8202e49b 4116ac10 4fc3f415 ae52f917""") - m = b2a_hex(b("abc")) - m_hash = _sws("""a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d""") - r = _sws("""8bac1ab6 6410435c b7181f95 b16ab97c 92b341c0""") - s = _sws("""41e2345f 1f56df24 58f426d1 55b4ba2d b6dcd8c8""") - - def setUp(self): - global DSA, Random, bytes_to_long, size - from Crypto.PublicKey import DSA - from Crypto import Random - from Crypto.Util.number import bytes_to_long, inverse, size - - self.dsa = DSA - - def test_generate_1arg(self): - """DSA (default implementation) generated key (1 argument)""" - dsaObj = self.dsa.generate(1024) - self._check_private_key(dsaObj) - pub = dsaObj.public_key() - self._check_public_key(pub) - - def test_generate_2arg(self): - """DSA (default implementation) generated key (2 arguments)""" - dsaObj = self.dsa.generate(1024, Random.new().read) - self._check_private_key(dsaObj) - pub = dsaObj.public_key() - self._check_public_key(pub) - - def test_construct_4tuple(self): - """DSA (default implementation) constructed key (4-tuple)""" - (y, g, p, q) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q)] - dsaObj = self.dsa.construct((y, g, p, q)) - self._test_verification(dsaObj) - - def test_construct_5tuple(self): - """DSA (default implementation) constructed key (5-tuple)""" - (y, g, p, q, x) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q, self.x)] - dsaObj = self.dsa.construct((y, g, p, q, x)) - self._test_signing(dsaObj) - self._test_verification(dsaObj) - - def test_construct_bad_key4(self): - (y, g, p, q) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q)] - tup = (y, g, p+1, q) - self.assertRaises(ValueError, self.dsa.construct, tup) - - tup = (y, g, p, q+1) - self.assertRaises(ValueError, self.dsa.construct, tup) - - tup = (y, 1, p, q) - self.assertRaises(ValueError, self.dsa.construct, tup) - - def test_construct_bad_key5(self): - (y, g, p, q, x) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q, self.x)] - tup = (y, g, p, q, x+1) - self.assertRaises(ValueError, self.dsa.construct, tup) - - tup = (y, g, p, q, q+10) - self.assertRaises(ValueError, self.dsa.construct, tup) - - def _check_private_key(self, dsaObj): - # Check capabilities - self.assertEqual(1, dsaObj.has_private()) - self.assertEqual(1, dsaObj.can_sign()) - self.assertEqual(0, dsaObj.can_encrypt()) - - # Sanity check key data - self.assertEqual(1, dsaObj.p > dsaObj.q) # p > q - self.assertEqual(160, size(dsaObj.q)) # size(q) == 160 bits - self.assertEqual(0, (dsaObj.p - 1) % dsaObj.q) # q is a divisor of p-1 - self.assertEqual(dsaObj.y, pow(dsaObj.g, dsaObj.x, dsaObj.p)) # y == g**x mod p - self.assertEqual(1, 0 < dsaObj.x < dsaObj.q) # 0 < x < q - - def _check_public_key(self, dsaObj): - k = bytes_to_long(a2b_hex(self.k)) - m_hash = bytes_to_long(a2b_hex(self.m_hash)) - - # Check capabilities - self.assertEqual(0, dsaObj.has_private()) - self.assertEqual(1, dsaObj.can_sign()) - self.assertEqual(0, dsaObj.can_encrypt()) - - # Check that private parameters are all missing - self.assertEqual(0, hasattr(dsaObj, 'x')) - - # Sanity check key data - self.assertEqual(1, dsaObj.p > dsaObj.q) # p > q - self.assertEqual(160, size(dsaObj.q)) # size(q) == 160 bits - self.assertEqual(0, (dsaObj.p - 1) % dsaObj.q) # q is a divisor of p-1 - - # Public-only key objects should raise an error when .sign() is called - self.assertRaises(TypeError, dsaObj._sign, m_hash, k) - - # Check __eq__ and __ne__ - self.assertEqual(dsaObj.public_key() == dsaObj.public_key(),True) # assert_ - self.assertEqual(dsaObj.public_key() != dsaObj.public_key(),False) # failIf - - self.assertEqual(dsaObj.public_key(), dsaObj.publickey()) - - def _test_signing(self, dsaObj): - k = bytes_to_long(a2b_hex(self.k)) - m_hash = bytes_to_long(a2b_hex(self.m_hash)) - r = bytes_to_long(a2b_hex(self.r)) - s = bytes_to_long(a2b_hex(self.s)) - (r_out, s_out) = dsaObj._sign(m_hash, k) - self.assertEqual((r, s), (r_out, s_out)) - - def _test_verification(self, dsaObj): - m_hash = bytes_to_long(a2b_hex(self.m_hash)) - r = bytes_to_long(a2b_hex(self.r)) - s = bytes_to_long(a2b_hex(self.s)) - self.failUnless(dsaObj._verify(m_hash, (r, s))) - self.failIf(dsaObj._verify(m_hash + 1, (r, s))) - - def test_repr(self): - (y, g, p, q) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q)] - dsaObj = self.dsa.construct((y, g, p, q)) - repr(dsaObj) - - -class DSADomainTest(unittest.TestCase): - - def test_domain1(self): - """Verify we can generate new keys in a given domain""" - dsa_key_1 = DSA.generate(1024) - domain_params = dsa_key_1.domain() - - dsa_key_2 = DSA.generate(1024, domain=domain_params) - self.assertEqual(dsa_key_1.p, dsa_key_2.p) - self.assertEqual(dsa_key_1.q, dsa_key_2.q) - self.assertEqual(dsa_key_1.g, dsa_key_2.g) - - self.assertEqual(dsa_key_1.domain(), dsa_key_2.domain()) - - def _get_weak_domain(self): - - from Crypto.Math.Numbers import Integer - from Crypto.Math import Primality - - p = Integer(4) - while p.size_in_bits() != 1024 or Primality.test_probable_prime(p) != Primality.PROBABLY_PRIME: - q1 = Integer.random(exact_bits=80) - q2 = Integer.random(exact_bits=80) - q = q1 * q2 - z = Integer.random(exact_bits=1024-160) - p = z * q + 1 - - h = Integer(2) - g = 1 - while g == 1: - g = pow(h, z, p) - h += 1 - - return (p, q, g) - - - def test_generate_error_weak_domain(self): - """Verify that domain parameters with composite q are rejected""" - - domain_params = self._get_weak_domain() - self.assertRaises(ValueError, DSA.generate, 1024, domain=domain_params) - - - def test_construct_error_weak_domain(self): - """Verify that domain parameters with composite q are rejected""" - - from Crypto.Math.Numbers import Integer - - p, q, g = self._get_weak_domain() - y = pow(g, 89, p) - self.assertRaises(ValueError, DSA.construct, (y, g, p, q)) - - -def get_tests(config={}): - tests = [] - tests += list_test_cases(DSATest) - tests += list_test_cases(DSADomainTest) - return tests - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') - -# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/Crypto/SelfTest/PublicKey/test_ECC.py b/Crypto/SelfTest/PublicKey/test_ECC.py deleted file mode 100644 index ea07a9d..0000000 --- a/Crypto/SelfTest/PublicKey/test_ECC.py +++ /dev/null @@ -1,859 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2015, Legrandin -# 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 -import time -from Crypto.SelfTest.st_common import list_test_cases -from Crypto.SelfTest.loader import load_test_vectors - -from Crypto.PublicKey import ECC -from Crypto.PublicKey.ECC import EccPoint, _curves, EccKey - -from Crypto.Math.Numbers import Integer - -class TestEccPoint(unittest.TestCase): - - def test_mix(self): - - p1 = ECC.generate(curve='P-256').pointQ - p2 = ECC.generate(curve='P-384').pointQ - - try: - p1 + p2 - assert(False) - except ValueError as e: - assert "not on the same curve" in str(e) - - try: - p1 += p2 - assert(False) - except ValueError as e: - assert "not on the same curve" in str(e) - - def test_repr(self): - p1 = ECC.construct(curve='P-256', - d=75467964919405407085864614198393977741148485328036093939970922195112333446269, - point_x=20573031766139722500939782666697015100983491952082159880539639074939225934381, - point_y=108863130203210779921520632367477406025152638284581252625277850513266505911389) - self.assertEqual(repr(p1), "EccKey(curve='NIST P-256', point_x=20573031766139722500939782666697015100983491952082159880539639074939225934381, point_y=108863130203210779921520632367477406025152638284581252625277850513266505911389, d=75467964919405407085864614198393977741148485328036093939970922195112333446269)") - - -class TestEccPoint_NIST_P256(unittest.TestCase): - """Tests defined in section 4.3 of https://www.nsa.gov/ia/_files/nist-routines.pdf""" - - pointS = EccPoint( - 0xde2444bebc8d36e682edd27e0f271508617519b3221a8fa0b77cab3989da97c9, - 0xc093ae7ff36e5380fc01a5aad1e66659702de80f53cec576b6350b243042a256) - - pointT = EccPoint( - 0x55a8b00f8da1d44e62f6b3b25316212e39540dc861c89575bb8cf92e35e0986b, - 0x5421c3209c2d6c704835d82ac4c3dd90f61a8a52598b9e7ab656e9d8c8b24316) - - def test_set(self): - pointW = EccPoint(0, 0) - pointW.set(self.pointS) - self.assertEqual(pointW, self.pointS) - - def test_copy(self): - pointW = self.pointS.copy() - self.assertEqual(pointW, self.pointS) - pointW.set(self.pointT) - self.assertEqual(pointW, self.pointT) - self.assertNotEqual(self.pointS, self.pointT) - - def test_negate(self): - negS = -self.pointS - sum = self.pointS + negS - self.assertEqual(sum, self.pointS.point_at_infinity()) - - def test_addition(self): - pointRx = 0x72b13dd4354b6b81745195e98cc5ba6970349191ac476bd4553cf35a545a067e - pointRy = 0x8d585cbb2e1327d75241a8a122d7620dc33b13315aa5c9d46d013011744ac264 - - pointR = self.pointS + self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS + pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai + self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai + pai - self.assertEqual(pointR, pai) - - def test_inplace_addition(self): - pointRx = 0x72b13dd4354b6b81745195e98cc5ba6970349191ac476bd4553cf35a545a067e - pointRy = 0x8d585cbb2e1327d75241a8a122d7620dc33b13315aa5c9d46d013011744ac264 - - pointR = self.pointS.copy() - pointR += self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS.copy() - pointR += pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai.copy() - pointR += self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai.copy() - pointR += pai - self.assertEqual(pointR, pai) - - def test_doubling(self): - pointRx = 0x7669e6901606ee3ba1a8eef1e0024c33df6c22f3b17481b82a860ffcdb6127b0 - pointRy = 0xfa878162187a54f6c39f6ee0072f33de389ef3eecd03023de10ca2c1db61d0c7 - - pointR = self.pointS.copy() - pointR.double() - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 2*0 - pai = self.pointS.point_at_infinity() - pointR = pai.copy() - pointR.double() - self.assertEqual(pointR, pai) - - # S + S - pointR = self.pointS.copy() - pointR += pointR - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_scalar_multiply(self): - d = 0xc51e4753afdec1e6b6c6a5b992f43f8dd0c7a8933072708b6522468b2ffb06fd - pointRx = 0x51d08d5f2d4278882946d88d83c97d11e62becc3cfc18bedacc89ba34eeca03f - pointRy = 0x75ee68eb8bf626aa5b673ab51f6e744e06f8fcf8a6c0cf3035beca956a7b41d5 - - pointR = self.pointS * d - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 0*S - pai = self.pointS.point_at_infinity() - pointR = self.pointS * 0 - self.assertEqual(pointR, pai) - - # -1*S - self.assertRaises(ValueError, lambda: self.pointS * -1) - - # Reverse order - pointR = d * self.pointS - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pointR = Integer(d) * self.pointS - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - - def test_joing_scalar_multiply(self): - d = 0xc51e4753afdec1e6b6c6a5b992f43f8dd0c7a8933072708b6522468b2ffb06fd - e = 0xd37f628ece72a462f0145cbefe3f0b355ee8332d37acdd83a358016aea029db7 - pointRx = 0xd867b4679221009234939221b8046245efcf58413daacbeff857b8588341f6b8 - pointRy = 0xf2504055c03cede12d22720dad69c745106b6607ec7e50dd35d54bd80f615275 - - t = self.pointS * d - - pointR = self.pointS * d + self.pointT * e - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_sizes(self): - self.assertEqual(self.pointS.size_in_bits(), 256) - self.assertEqual(self.pointS.size_in_bytes(), 32) - -class TestEccPoint_NIST_P384(unittest.TestCase): - """Tests defined in section 4.4 of https://www.nsa.gov/ia/_files/nist-routines.pdf""" - - pointS = EccPoint( - 0xfba203b81bbd23f2b3be971cc23997e1ae4d89e69cb6f92385dda82768ada415ebab4167459da98e62b1332d1e73cb0e, - 0x5ffedbaefdeba603e7923e06cdb5d0c65b22301429293376d5c6944e3fa6259f162b4788de6987fd59aed5e4b5285e45, - "p384") - - pointT = EccPoint( - 0xaacc05202e7fda6fc73d82f0a66220527da8117ee8f8330ead7d20ee6f255f582d8bd38c5a7f2b40bcdb68ba13d81051, - 0x84009a263fefba7c2c57cffa5db3634d286131afc0fca8d25afa22a7b5dce0d9470da89233cee178592f49b6fecb5092, - "p384") - - def test_set(self): - pointW = EccPoint(0, 0, "p384") - pointW.set(self.pointS) - self.assertEqual(pointW, self.pointS) - - def test_copy(self): - pointW = self.pointS.copy() - self.assertEqual(pointW, self.pointS) - pointW.set(self.pointT) - self.assertEqual(pointW, self.pointT) - self.assertNotEqual(self.pointS, self.pointT) - - def test_negate(self): - negS = -self.pointS - sum = self.pointS + negS - self.assertEqual(sum, self.pointS.point_at_infinity()) - - def test_addition(self): - pointRx = 0x12dc5ce7acdfc5844d939f40b4df012e68f865b89c3213ba97090a247a2fc009075cf471cd2e85c489979b65ee0b5eed - pointRy = 0x167312e58fe0c0afa248f2854e3cddcb557f983b3189b67f21eee01341e7e9fe67f6ee81b36988efa406945c8804a4b0 - - pointR = self.pointS + self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS + pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai + self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai + pai - self.assertEqual(pointR, pai) - - def _test_inplace_addition(self): - pointRx = 0x72b13dd4354b6b81745195e98cc5ba6970349191ac476bd4553cf35a545a067e - pointRy = 0x8d585cbb2e1327d75241a8a122d7620dc33b13315aa5c9d46d013011744ac264 - - pointR = self.pointS.copy() - pointR += self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS.copy() - pointR += pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai.copy() - pointR += self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai.copy() - pointR += pai - self.assertEqual(pointR, pai) - - def test_doubling(self): - pointRx = 0x2a2111b1e0aa8b2fc5a1975516bc4d58017ff96b25e1bdff3c229d5fac3bacc319dcbec29f9478f42dee597b4641504c - pointRy = 0xfa2e3d9dc84db8954ce8085ef28d7184fddfd1344b4d4797343af9b5f9d837520b450f726443e4114bd4e5bdb2f65ddd - - pointR = self.pointS.copy() - pointR.double() - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 2*0 - pai = self.pointS.point_at_infinity() - pointR = pai.copy() - pointR.double() - self.assertEqual(pointR, pai) - - # S + S - pointR = self.pointS.copy() - pointR += pointR - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_scalar_multiply(self): - d = 0xa4ebcae5a665983493ab3e626085a24c104311a761b5a8fdac052ed1f111a5c44f76f45659d2d111a61b5fdd97583480 - pointRx = 0xe4f77e7ffeb7f0958910e3a680d677a477191df166160ff7ef6bb5261f791aa7b45e3e653d151b95dad3d93ca0290ef2 - pointRy = 0xac7dee41d8c5f4a7d5836960a773cfc1376289d3373f8cf7417b0c6207ac32e913856612fc9ff2e357eb2ee05cf9667f - - pointR = self.pointS * d - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 0*S - pai = self.pointS.point_at_infinity() - pointR = self.pointS * 0 - self.assertEqual(pointR, pai) - - # -1*S - self.assertRaises(ValueError, lambda: self.pointS * -1) - - def test_joing_scalar_multiply(self): - d = 0xa4ebcae5a665983493ab3e626085a24c104311a761b5a8fdac052ed1f111a5c44f76f45659d2d111a61b5fdd97583480 - e = 0xafcf88119a3a76c87acbd6008e1349b29f4ba9aa0e12ce89bcfcae2180b38d81ab8cf15095301a182afbc6893e75385d - pointRx = 0x917ea28bcd641741ae5d18c2f1bd917ba68d34f0f0577387dc81260462aea60e2417b8bdc5d954fc729d211db23a02dc - pointRy = 0x1a29f7ce6d074654d77b40888c73e92546c8f16a5ff6bcbd307f758d4aee684beff26f6742f597e2585c86da908f7186 - - t = self.pointS * d - - pointR = self.pointS * d + self.pointT * e - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_sizes(self): - self.assertEqual(self.pointS.size_in_bits(), 384) - self.assertEqual(self.pointS.size_in_bytes(), 48) - - -class TestEccPoint_NIST_P521(unittest.TestCase): - """Tests defined in section 4.5 of https://www.nsa.gov/ia/_files/nist-routines.pdf""" - - pointS = EccPoint( - 0x000001d5c693f66c08ed03ad0f031f937443458f601fd098d3d0227b4bf62873af50740b0bb84aa157fc847bcf8dc16a8b2b8bfd8e2d0a7d39af04b089930ef6dad5c1b4, - 0x00000144b7770963c63a39248865ff36b074151eac33549b224af5c8664c54012b818ed037b2b7c1a63ac89ebaa11e07db89fcee5b556e49764ee3fa66ea7ae61ac01823, - "p521") - - pointT = EccPoint( - 0x000000f411f2ac2eb971a267b80297ba67c322dba4bb21cec8b70073bf88fc1ca5fde3ba09e5df6d39acb2c0762c03d7bc224a3e197feaf760d6324006fe3be9a548c7d5, - 0x000001fdf842769c707c93c630df6d02eff399a06f1b36fb9684f0b373ed064889629abb92b1ae328fdb45534268384943f0e9222afe03259b32274d35d1b9584c65e305, - "p521") - - def test_set(self): - pointW = EccPoint(0, 0) - pointW.set(self.pointS) - self.assertEqual(pointW, self.pointS) - - def test_copy(self): - pointW = self.pointS.copy() - self.assertEqual(pointW, self.pointS) - pointW.set(self.pointT) - self.assertEqual(pointW, self.pointT) - self.assertNotEqual(self.pointS, self.pointT) - - def test_negate(self): - negS = -self.pointS - sum = self.pointS + negS - self.assertEqual(sum, self.pointS.point_at_infinity()) - - def test_addition(self): - pointRx = 0x000001264ae115ba9cbc2ee56e6f0059e24b52c8046321602c59a339cfb757c89a59c358a9a8e1f86d384b3f3b255ea3f73670c6dc9f45d46b6a196dc37bbe0f6b2dd9e9 - pointRy = 0x00000062a9c72b8f9f88a271690bfa017a6466c31b9cadc2fc544744aeb817072349cfddc5ad0e81b03f1897bd9c8c6efbdf68237dc3bb00445979fb373b20c9a967ac55 - - pointR = self.pointS + self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS + pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai + self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai + pai - self.assertEqual(pointR, pai) - - def test_inplace_addition(self): - pointRx = 0x000001264ae115ba9cbc2ee56e6f0059e24b52c8046321602c59a339cfb757c89a59c358a9a8e1f86d384b3f3b255ea3f73670c6dc9f45d46b6a196dc37bbe0f6b2dd9e9 - pointRy = 0x00000062a9c72b8f9f88a271690bfa017a6466c31b9cadc2fc544744aeb817072349cfddc5ad0e81b03f1897bd9c8c6efbdf68237dc3bb00445979fb373b20c9a967ac55 - - pointR = self.pointS.copy() - pointR += self.pointT - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - pai = pointR.point_at_infinity() - - # S + 0 - pointR = self.pointS.copy() - pointR += pai - self.assertEqual(pointR, self.pointS) - - # 0 + S - pointR = pai.copy() - pointR += self.pointS - self.assertEqual(pointR, self.pointS) - - # 0 + 0 - pointR = pai.copy() - pointR += pai - self.assertEqual(pointR, pai) - - def test_doubling(self): - pointRx = 0x0000012879442f2450c119e7119a5f738be1f1eba9e9d7c6cf41b325d9ce6d643106e9d61124a91a96bcf201305a9dee55fa79136dc700831e54c3ca4ff2646bd3c36bc6 - pointRy = 0x0000019864a8b8855c2479cbefe375ae553e2393271ed36fadfc4494fc0583f6bd03598896f39854abeae5f9a6515a021e2c0eef139e71de610143f53382f4104dccb543 - - pointR = self.pointS.copy() - pointR.double() - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 2*0 - pai = self.pointS.point_at_infinity() - pointR = pai.copy() - pointR.double() - self.assertEqual(pointR, pai) - - # S + S - pointR = self.pointS.copy() - pointR += pointR - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_scalar_multiply(self): - d = 0x000001eb7f81785c9629f136a7e8f8c674957109735554111a2a866fa5a166699419bfa9936c78b62653964df0d6da940a695c7294d41b2d6600de6dfcf0edcfc89fdcb1 - pointRx = 0x00000091b15d09d0ca0353f8f96b93cdb13497b0a4bb582ae9ebefa35eee61bf7b7d041b8ec34c6c00c0c0671c4ae063318fb75be87af4fe859608c95f0ab4774f8c95bb - pointRy = 0x00000130f8f8b5e1abb4dd94f6baaf654a2d5810411e77b7423965e0c7fd79ec1ae563c207bd255ee9828eb7a03fed565240d2cc80ddd2cecbb2eb50f0951f75ad87977f - - pointR = self.pointS * d - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - # 0*S - pai = self.pointS.point_at_infinity() - pointR = self.pointS * 0 - self.assertEqual(pointR, pai) - - # -1*S - self.assertRaises(ValueError, lambda: self.pointS * -1) - - def test_joing_scalar_multiply(self): - d = 0x000001eb7f81785c9629f136a7e8f8c674957109735554111a2a866fa5a166699419bfa9936c78b62653964df0d6da940a695c7294d41b2d6600de6dfcf0edcfc89fdcb1 - e = 0x00000137e6b73d38f153c3a7575615812608f2bab3229c92e21c0d1c83cfad9261dbb17bb77a63682000031b9122c2f0cdab2af72314be95254de4291a8f85f7c70412e3 - pointRx = 0x0000009d3802642b3bea152beb9e05fba247790f7fc168072d363340133402f2585588dc1385d40ebcb8552f8db02b23d687cae46185b27528adb1bf9729716e4eba653d - pointRy = 0x0000000fe44344e79da6f49d87c1063744e5957d9ac0a505bafa8281c9ce9ff25ad53f8da084a2deb0923e46501de5797850c61b229023dd9cf7fc7f04cd35ebb026d89d - - t = self.pointS * d - - pointR = self.pointS * d - pointR += self.pointT * e - self.assertEqual(pointR.x, pointRx) - self.assertEqual(pointR.y, pointRy) - - def test_sizes(self): - self.assertEqual(self.pointS.size_in_bits(), 521) - self.assertEqual(self.pointS.size_in_bytes(), 66) - - -class TestEccPoint_PAI_P256(unittest.TestCase): - """Test vectors from http://point-at-infinity.org/ecc/nisttv""" - - curve = _curves['p256'] - pointG = EccPoint(curve.Gx, curve.Gy, "p256") - - -tv_pai = load_test_vectors(("PublicKey", "ECC"), - "point-at-infinity.org-P256.txt", - "P-256 tests from point-at-infinity.org", - {"k": lambda k: int(k), - "x": lambda x: int(x, 16), - "y": lambda y: int(y, 16)}) or [] -for tv in tv_pai: - def new_test(self, scalar=tv.k, x=tv.x, y=tv.y): - result = self.pointG * scalar - self.assertEqual(result.x, x) - self.assertEqual(result.y, y) - setattr(TestEccPoint_PAI_P256, "test_%d" % tv.count, new_test) - - -class TestEccPoint_PAI_P384(unittest.TestCase): - """Test vectors from http://point-at-infinity.org/ecc/nisttv""" - - curve = _curves['p384'] - pointG = EccPoint(curve.Gx, curve.Gy, "p384") - - -tv_pai = load_test_vectors(("PublicKey", "ECC"), - "point-at-infinity.org-P384.txt", - "P-384 tests from point-at-infinity.org", - {"k" : lambda k: int(k), - "x" : lambda x: int(x, 16), - "y" : lambda y: int(y, 16)}) or [] -for tv in tv_pai: - def new_test(self, scalar=tv.k, x=tv.x, y=tv.y): - result = self.pointG * scalar - self.assertEqual(result.x, x) - self.assertEqual(result.y, y) - setattr(TestEccPoint_PAI_P384, "test_%d" % tv.count, new_test) - - -class TestEccPoint_PAI_P521(unittest.TestCase): - """Test vectors from http://point-at-infinity.org/ecc/nisttv""" - - curve = _curves['p521'] - pointG = EccPoint(curve.Gx, curve.Gy, "p521") - - -tv_pai = load_test_vectors(("PublicKey", "ECC"), - "point-at-infinity.org-P521.txt", - "P-521 tests from point-at-infinity.org", - {"k": lambda k: int(k), - "x": lambda x: int(x, 16), - "y": lambda y: int(y, 16)}) or [] -for tv in tv_pai: - def new_test(self, scalar=tv.k, x=tv.x, y=tv.y): - result = self.pointG * scalar - self.assertEqual(result.x, x) - self.assertEqual(result.y, y) - setattr(TestEccPoint_PAI_P521, "test_%d" % tv.count, new_test) - - -class TestEccKey_P256(unittest.TestCase): - - def test_private_key(self): - - key = EccKey(curve="P-256", d=1) - self.assertEqual(key.d, 1) - self.failUnless(key.has_private()) - self.assertEqual(key.pointQ.x, _curves['p256'].Gx) - self.assertEqual(key.pointQ.y, _curves['p256'].Gy) - - point = EccPoint(_curves['p256'].Gx, _curves['p256'].Gy) - key = EccKey(curve="P-256", d=1, point=point) - self.assertEqual(key.d, 1) - self.failUnless(key.has_private()) - self.assertEqual(key.pointQ, point) - - # Other names - key = EccKey(curve="secp256r1", d=1) - key = EccKey(curve="prime256v1", d=1) - - def test_public_key(self): - - point = EccPoint(_curves['p256'].Gx, _curves['p256'].Gy) - key = EccKey(curve="P-256", point=point) - self.failIf(key.has_private()) - self.assertEqual(key.pointQ, point) - - def test_public_key_derived(self): - - priv_key = EccKey(curve="P-256", d=3) - pub_key = priv_key.public_key() - self.failIf(pub_key.has_private()) - self.assertEqual(priv_key.pointQ, pub_key.pointQ) - - def test_invalid_curve(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-257", d=1)) - - def test_invalid_d(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-256", d=0)) - self.assertRaises(ValueError, lambda: EccKey(curve="P-256", d=_curves['p256'].order)) - - def test_equality(self): - - private_key = ECC.construct(d=3, curve="P-256") - private_key2 = ECC.construct(d=3, curve="P-256") - private_key3 = ECC.construct(d=4, curve="P-256") - - public_key = private_key.public_key() - public_key2 = private_key2.public_key() - public_key3 = private_key3.public_key() - - self.assertEqual(private_key, private_key2) - self.assertNotEqual(private_key, private_key3) - - self.assertEqual(public_key, public_key2) - self.assertNotEqual(public_key, public_key3) - - self.assertNotEqual(public_key, private_key) - - -class TestEccKey_P384(unittest.TestCase): - - def test_private_key(self): - - p384 = _curves['p384'] - - key = EccKey(curve="P-384", d=1) - self.assertEqual(key.d, 1) - self.failUnless(key.has_private()) - self.assertEqual(key.pointQ.x, p384.Gx) - self.assertEqual(key.pointQ.y, p384.Gy) - - point = EccPoint(p384.Gx, p384.Gy, "p384") - key = EccKey(curve="P-384", d=1, point=point) - self.assertEqual(key.d, 1) - self.failUnless(key.has_private()) - self.assertEqual(key.pointQ, point) - - # Other names - key = EccKey(curve="p384", d=1) - key = EccKey(curve="secp384r1", d=1) - key = EccKey(curve="prime384v1", d=1) - - def test_public_key(self): - - p384 = _curves['p384'] - point = EccPoint(p384.Gx, p384.Gy, 'p384') - key = EccKey(curve="P-384", point=point) - self.failIf(key.has_private()) - self.assertEqual(key.pointQ, point) - - def test_public_key_derived(self): - - priv_key = EccKey(curve="P-384", d=3) - pub_key = priv_key.public_key() - self.failIf(pub_key.has_private()) - self.assertEqual(priv_key.pointQ, pub_key.pointQ) - - def test_invalid_curve(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-385", d=1)) - - def test_invalid_d(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-384", d=0)) - self.assertRaises(ValueError, lambda: EccKey(curve="P-384", - d=_curves['p384'].order)) - - def test_equality(self): - - private_key = ECC.construct(d=3, curve="P-384") - private_key2 = ECC.construct(d=3, curve="P-384") - private_key3 = ECC.construct(d=4, curve="P-384") - - public_key = private_key.public_key() - public_key2 = private_key2.public_key() - public_key3 = private_key3.public_key() - - self.assertEqual(private_key, private_key2) - self.assertNotEqual(private_key, private_key3) - - self.assertEqual(public_key, public_key2) - self.assertNotEqual(public_key, public_key3) - - self.assertNotEqual(public_key, private_key) - - -class TestEccKey_P521(unittest.TestCase): - - def test_private_key(self): - - p521 = _curves['p521'] - - key = EccKey(curve="P-521", d=1) - self.assertEqual(key.d, 1) - self.failUnless(key.has_private()) - self.assertEqual(key.pointQ.x, p521.Gx) - self.assertEqual(key.pointQ.y, p521.Gy) - - point = EccPoint(p521.Gx, p521.Gy, "p521") - key = EccKey(curve="P-521", d=1, point=point) - self.assertEqual(key.d, 1) - self.failUnless(key.has_private()) - self.assertEqual(key.pointQ, point) - - # Other names - key = EccKey(curve="p521", d=1) - key = EccKey(curve="secp521r1", d=1) - key = EccKey(curve="prime521v1", d=1) - - def test_public_key(self): - - p521 = _curves['p521'] - point = EccPoint(p521.Gx, p521.Gy, 'p521') - key = EccKey(curve="P-384", point=point) - self.failIf(key.has_private()) - self.assertEqual(key.pointQ, point) - - def test_public_key_derived(self): - - priv_key = EccKey(curve="P-521", d=3) - pub_key = priv_key.public_key() - self.failIf(pub_key.has_private()) - self.assertEqual(priv_key.pointQ, pub_key.pointQ) - - def test_invalid_curve(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-522", d=1)) - - def test_invalid_d(self): - self.assertRaises(ValueError, lambda: EccKey(curve="P-521", d=0)) - self.assertRaises(ValueError, lambda: EccKey(curve="P-521", - d=_curves['p521'].order)) - - def test_equality(self): - - private_key = ECC.construct(d=3, curve="P-521") - private_key2 = ECC.construct(d=3, curve="P-521") - private_key3 = ECC.construct(d=4, curve="P-521") - - public_key = private_key.public_key() - public_key2 = private_key2.public_key() - public_key3 = private_key3.public_key() - - self.assertEqual(private_key, private_key2) - self.assertNotEqual(private_key, private_key3) - - self.assertEqual(public_key, public_key2) - self.assertNotEqual(public_key, public_key3) - - self.assertNotEqual(public_key, private_key) - - -class TestEccModule_P256(unittest.TestCase): - - def test_generate(self): - - key = ECC.generate(curve="P-256") - self.failUnless(key.has_private()) - self.assertEqual(key.pointQ, EccPoint(_curves['p256'].Gx, - _curves['p256'].Gy) * key.d, - "p256") - - # Other names - ECC.generate(curve="secp256r1") - ECC.generate(curve="prime256v1") - - def test_construct(self): - - key = ECC.construct(curve="P-256", d=1) - self.failUnless(key.has_private()) - self.assertEqual(key.pointQ, _curves['p256'].G) - - key = ECC.construct(curve="P-256", point_x=_curves['p256'].Gx, - point_y=_curves['p256'].Gy) - self.failIf(key.has_private()) - self.assertEqual(key.pointQ, _curves['p256'].G) - - # Other names - ECC.construct(curve="p256", d=1) - ECC.construct(curve="secp256r1", d=1) - ECC.construct(curve="prime256v1", d=1) - - def test_negative_construct(self): - coord = dict(point_x=10, point_y=4) - coordG = dict(point_x=_curves['p256'].Gx, point_y=_curves['p256'].Gy) - - self.assertRaises(ValueError, ECC.construct, curve="P-256", **coord) - self.assertRaises(ValueError, ECC.construct, curve="P-256", d=2, **coordG) - - -class TestEccModule_P384(unittest.TestCase): - - def test_generate(self): - - curve = _curves['p384'] - key = ECC.generate(curve="P-384") - self.failUnless(key.has_private()) - self.assertEqual(key.pointQ, EccPoint(curve.Gx, curve.Gy, "p384") * key.d) - - # Other names - ECC.generate(curve="secp384r1") - ECC.generate(curve="prime384v1") - - def test_construct(self): - - curve = _curves['p384'] - key = ECC.construct(curve="P-384", d=1) - self.failUnless(key.has_private()) - self.assertEqual(key.pointQ, _curves['p384'].G) - - key = ECC.construct(curve="P-384", point_x=curve.Gx, point_y=curve.Gy) - self.failIf(key.has_private()) - self.assertEqual(key.pointQ, curve.G) - - # Other names - ECC.construct(curve="p384", d=1) - ECC.construct(curve="secp384r1", d=1) - ECC.construct(curve="prime384v1", d=1) - - def test_negative_construct(self): - coord = dict(point_x=10, point_y=4) - coordG = dict(point_x=_curves['p384'].Gx, point_y=_curves['p384'].Gy) - - self.assertRaises(ValueError, ECC.construct, curve="P-384", **coord) - self.assertRaises(ValueError, ECC.construct, curve="P-384", d=2, **coordG) - - -class TestEccModule_P521(unittest.TestCase): - - def test_generate(self): - - curve = _curves['p521'] - key = ECC.generate(curve="P-521") - self.failUnless(key.has_private()) - self.assertEqual(key.pointQ, EccPoint(curve.Gx, curve.Gy, "p521") * key.d) - - # Other names - ECC.generate(curve="secp521r1") - ECC.generate(curve="prime521v1") - - def test_construct(self): - - curve = _curves['p521'] - key = ECC.construct(curve="P-521", d=1) - self.failUnless(key.has_private()) - self.assertEqual(key.pointQ, _curves['p521'].G) - - key = ECC.construct(curve="P-521", point_x=curve.Gx, point_y=curve.Gy) - self.failIf(key.has_private()) - self.assertEqual(key.pointQ, curve.G) - - # Other names - ECC.construct(curve="p521", d=1) - ECC.construct(curve="secp521r1", d=1) - ECC.construct(curve="prime521v1", d=1) - - def test_negative_construct(self): - coord = dict(point_x=10, point_y=4) - coordG = dict(point_x=_curves['p521'].Gx, point_y=_curves['p521'].Gy) - - self.assertRaises(ValueError, ECC.construct, curve="P-521", **coord) - self.assertRaises(ValueError, ECC.construct, curve="P-521", d=2, **coordG) - - -def get_tests(config={}): - tests = [] - tests += list_test_cases(TestEccPoint) - tests += list_test_cases(TestEccPoint_NIST_P256) - tests += list_test_cases(TestEccPoint_NIST_P384) - tests += list_test_cases(TestEccPoint_NIST_P521) - tests += list_test_cases(TestEccPoint_PAI_P256) - tests += list_test_cases(TestEccPoint_PAI_P384) - tests += list_test_cases(TestEccPoint_PAI_P521) - tests += list_test_cases(TestEccKey_P256) - tests += list_test_cases(TestEccKey_P384) - tests += list_test_cases(TestEccKey_P521) - tests += list_test_cases(TestEccModule_P256) - tests += list_test_cases(TestEccModule_P384) - tests += list_test_cases(TestEccModule_P521) - return tests - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/PublicKey/test_ElGamal.py b/Crypto/SelfTest/PublicKey/test_ElGamal.py deleted file mode 100644 index 0af6738..0000000 --- a/Crypto/SelfTest/PublicKey/test_ElGamal.py +++ /dev/null @@ -1,217 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/PublicKey/test_ElGamal.py: Self-test for the ElGamal primitive -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-test suite for Crypto.PublicKey.ElGamal""" - -__revision__ = "$Id$" - -import unittest -from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex -from Crypto import Random -from Crypto.PublicKey import ElGamal -from Crypto.Util.number import bytes_to_long -from Crypto.Util.py3compat import * - -class ElGamalTest(unittest.TestCase): - - # - # Test vectors - # - # There seem to be no real ElGamal test vectors available in the - # public domain. The following test vectors have been generated - # with libgcrypt 1.5.0. - # - # Encryption - tve=[ - { - # 256 bits - 'p' :'BA4CAEAAED8CBE952AFD2126C63EB3B345D65C2A0A73D2A3AD4138B6D09BD933', - 'g' :'05', - 'y' :'60D063600ECED7C7C55146020E7A31C4476E9793BEAED420FEC9E77604CAE4EF', - 'x' :'1D391BA2EE3C37FE1BA175A69B2C73A11238AD77675932', - 'k' :'F5893C5BAB4131264066F57AB3D8AD89E391A0B68A68A1', - 'pt' :'48656C6C6F207468657265', - 'ct1':'32BFD5F487966CEA9E9356715788C491EC515E4ED48B58F0F00971E93AAA5EC7', - 'ct2':'7BE8FBFF317C93E82FCEF9BD515284BA506603FEA25D01C0CB874A31F315EE68' - }, - - { - # 512 bits - 'p' :'F1B18AE9F7B4E08FDA9A04832F4E919D89462FD31BF12F92791A93519F75076D6CE3942689CDFF2F344CAFF0F82D01864F69F3AECF566C774CBACF728B81A227', - 'g' :'07', - 'y' :'688628C676E4F05D630E1BE39D0066178CA7AA83836B645DE5ADD359B4825A12B02EF4252E4E6FA9BEC1DB0BE90F6D7C8629CABB6E531F472B2664868156E20C', - 'x' :'14E60B1BDFD33436C0DA8A22FDC14A2CCDBBED0627CE68', - 'k' :'38DBF14E1F319BDA9BAB33EEEADCAF6B2EA5250577ACE7', - 'pt' :'48656C6C6F207468657265', - 'ct1':'290F8530C2CC312EC46178724F196F308AD4C523CEABB001FACB0506BFED676083FE0F27AC688B5C749AB3CB8A80CD6F7094DBA421FB19442F5A413E06A9772B', - 'ct2':'1D69AAAD1DC50493FB1B8E8721D621D683F3BF1321BE21BC4A43E11B40C9D4D9C80DE3AAC2AB60D31782B16B61112E68220889D53C4C3136EE6F6CE61F8A23A0' - } - ] - - # Signature - tvs=[ - { - # 256 bits - 'p' :'D2F3C41EA66530838A704A48FFAC9334F4701ECE3A97CEE4C69DD01AE7129DD7', - 'g' :'05', - 'y' :'C3F9417DC0DAFEA6A05C1D2333B7A95E63B3F4F28CC962254B3256984D1012E7', - 'x' :'165E4A39BE44D5A2D8B1332D416BC559616F536BC735BB', - 'k' :'C7F0C794A7EAD726E25A47FF8928013680E73C51DD3D7D99BFDA8F492585928F', - 'h' :'48656C6C6F207468657265', - 'sig1':'35CA98133779E2073EF31165AFCDEB764DD54E96ADE851715495F9C635E1E7C2', - 'sig2':'0135B88B1151279FE5D8078D4FC685EE81177EE9802AB123A73925FC1CB059A7', - }, - { - # 512 bits - 'p' :'E24CF3A4B8A6AF749DCA6D714282FE4AABEEE44A53BB6ED15FBE32B5D3C3EF9CC4124A2ECA331F3C1C1B667ACA3766825217E7B5F9856648D95F05330C6A19CF', - 'g' :'0B', - 'y' :'2AD3A1049CA5D4ED207B2431C79A8719BB4073D4A94E450EA6CEE8A760EB07ADB67C0D52C275EE85D7B52789061EE45F2F37D9B2AE522A51C28329766BFE68AC', - 'x' :'16CBB4F46D9ECCF24FF9F7E63CAA3BD8936341555062AB', - 'k' :'8A3D89A4E429FD2476D7D717251FB79BF900FFE77444E6BB8299DC3F84D0DD57ABAB50732AE158EA52F5B9E7D8813E81FD9F79470AE22F8F1CF9AEC820A78C69', - 'h' :'48656C6C6F207468657265', - 'sig1':'BE001AABAFFF976EC9016198FBFEA14CBEF96B000CCC0063D3324016F9E91FE80D8F9325812ED24DDB2B4D4CF4430B169880B3CE88313B53255BD4EC0378586F', - 'sig2':'5E266F3F837BA204E3BBB6DBECC0611429D96F8C7CE8F4EFDF9D4CB681C2A954468A357BF4242CEC7418B51DFC081BCD21299EF5B5A0DDEF3A139A1817503DDE', - } - ] - - def test_generate_180(self): - self._test_random_key(180) - - def test_encryption(self): - for tv in self.tve: - d = self.convert_tv(tv, True) - key = ElGamal.construct(d['key']) - ct = key._encrypt(d['pt'], d['k']) - self.assertEquals(ct[0], d['ct1']) - self.assertEquals(ct[1], d['ct2']) - - def test_decryption(self): - for tv in self.tve: - d = self.convert_tv(tv, True) - key = ElGamal.construct(d['key']) - pt = key._decrypt((d['ct1'], d['ct2'])) - self.assertEquals(pt, d['pt']) - - def test_signing(self): - for tv in self.tvs: - d = self.convert_tv(tv, True) - key = ElGamal.construct(d['key']) - sig1, sig2 = key._sign(d['h'], d['k']) - self.assertEquals(sig1, d['sig1']) - self.assertEquals(sig2, d['sig2']) - - def test_verification(self): - for tv in self.tvs: - d = self.convert_tv(tv, True) - key = ElGamal.construct(d['key']) - # Positive test - res = key._verify( d['h'], (d['sig1'],d['sig2']) ) - self.failUnless(res) - # Negative test - res = key._verify( d['h'], (d['sig1']+1,d['sig2']) ) - self.failIf(res) - - def test_bad_key3(self): - tup = tup0 = list(self.convert_tv(self.tvs[0], 1)['key'])[:3] - tup[0] += 1 # p += 1 (not prime) - self.assertRaises(ValueError, ElGamal.construct, tup) - - tup = tup0 - tup[1] = 1 # g = 1 - self.assertRaises(ValueError, ElGamal.construct, tup) - - tup = tup0 - tup[2] = tup[0]*2 # y = 2*p - self.assertRaises(ValueError, ElGamal.construct, tup) - - def test_bad_key4(self): - tup = tup0 = list(self.convert_tv(self.tvs[0], 1)['key']) - tup[3] += 1 # x += 1 - self.assertRaises(ValueError, ElGamal.construct, tup) - - def convert_tv(self, tv, as_longs=0): - """Convert a test vector from textual form (hexadecimal ascii - to either integers or byte strings.""" - key_comps = 'p','g','y','x' - tv2 = {} - for c in tv.keys(): - tv2[c] = a2b_hex(tv[c]) - if as_longs or c in key_comps or c in ('sig1','sig2'): - tv2[c] = bytes_to_long(tv2[c]) - tv2['key']=[] - for c in key_comps: - tv2['key'] += [tv2[c]] - del tv2[c] - return tv2 - - def _test_random_key(self, bits): - elgObj = ElGamal.generate(bits, Random.new().read) - self._check_private_key(elgObj) - self._exercise_primitive(elgObj) - pub = elgObj.publickey() - self._check_public_key(pub) - self._exercise_public_primitive(elgObj) - - def _check_private_key(self, elgObj): - - # Check capabilities - self.failUnless(elgObj.has_private()) - - # Sanity check key data - self.failUnless(1 -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-test suite for Crypto.PublicKey.RSA""" - -__revision__ = "$Id$" - -import os -import pickle -from pickle import PicklingError -from Crypto.Util.py3compat import * - -import unittest -from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex - -class RSATest(unittest.TestCase): - # Test vectors from "RSA-OAEP and RSA-PSS test vectors (.zip file)" - # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip - # See RSADSI's PKCS#1 page at - # http://www.rsa.com/rsalabs/node.asp?id=2125 - - # from oaep-int.txt - - # TODO: PyCrypto treats the message as starting *after* the leading "00" - # TODO: That behaviour should probably be changed in the future. - plaintext = """ - eb 7a 19 ac e9 e3 00 63 50 e3 29 50 4b 45 e2 - ca 82 31 0b 26 dc d8 7d 5c 68 f1 ee a8 f5 52 67 - c3 1b 2e 8b b4 25 1f 84 d7 e0 b2 c0 46 26 f5 af - f9 3e dc fb 25 c9 c2 b3 ff 8a e1 0e 83 9a 2d db - 4c dc fe 4f f4 77 28 b4 a1 b7 c1 36 2b aa d2 9a - b4 8d 28 69 d5 02 41 21 43 58 11 59 1b e3 92 f9 - 82 fb 3e 87 d0 95 ae b4 04 48 db 97 2f 3a c1 4f - 7b c2 75 19 52 81 ce 32 d2 f1 b7 6d 4d 35 3e 2d - """ - - ciphertext = """ - 12 53 e0 4d c0 a5 39 7b b4 4a 7a b8 7e 9b f2 a0 - 39 a3 3d 1e 99 6f c8 2a 94 cc d3 00 74 c9 5d f7 - 63 72 20 17 06 9e 52 68 da 5d 1c 0b 4f 87 2c f6 - 53 c1 1d f8 23 14 a6 79 68 df ea e2 8d ef 04 bb - 6d 84 b1 c3 1d 65 4a 19 70 e5 78 3b d6 eb 96 a0 - 24 c2 ca 2f 4a 90 fe 9f 2e f5 c9 c1 40 e5 bb 48 - da 95 36 ad 87 00 c8 4f c9 13 0a de a7 4e 55 8d - 51 a7 4d df 85 d8 b5 0d e9 68 38 d6 06 3e 09 55 - """ - - modulus = """ - bb f8 2f 09 06 82 ce 9c 23 38 ac 2b 9d a8 71 f7 - 36 8d 07 ee d4 10 43 a4 40 d6 b6 f0 74 54 f5 1f - b8 df ba af 03 5c 02 ab 61 ea 48 ce eb 6f cd 48 - 76 ed 52 0d 60 e1 ec 46 19 71 9d 8a 5b 8b 80 7f - af b8 e0 a3 df c7 37 72 3e e6 b4 b7 d9 3a 25 84 - ee 6a 64 9d 06 09 53 74 88 34 b2 45 45 98 39 4e - e0 aa b1 2d 7b 61 a5 1f 52 7a 9a 41 f6 c1 68 7f - e2 53 72 98 ca 2a 8f 59 46 f8 e5 fd 09 1d bd cb - """ - - e = 0x11 # public exponent - - prime_factor = """ - c9 7f b1 f0 27 f4 53 f6 34 12 33 ea aa d1 d9 35 - 3f 6c 42 d0 88 66 b1 d0 5a 0f 20 35 02 8b 9d 86 - 98 40 b4 16 66 b4 2e 92 ea 0d a3 b4 32 04 b5 cf - ce 33 52 52 4d 04 16 a5 a4 41 e7 00 af 46 15 03 - """ - - def setUp(self): - global RSA, Random, bytes_to_long - from Crypto.PublicKey import RSA - from Crypto import Random - from Crypto.Util.number import bytes_to_long, inverse - self.n = bytes_to_long(a2b_hex(self.modulus)) - self.p = bytes_to_long(a2b_hex(self.prime_factor)) - - # Compute q, d, and u from n, e, and p - self.q = self.n // self.p - self.d = inverse(self.e, (self.p-1)*(self.q-1)) - self.u = inverse(self.p, self.q) # u = e**-1 (mod q) - - self.rsa = RSA - - def test_generate_1arg(self): - """RSA (default implementation) generated key (1 argument)""" - rsaObj = self.rsa.generate(1024) - self._check_private_key(rsaObj) - self._exercise_primitive(rsaObj) - pub = rsaObj.public_key() - self._check_public_key(pub) - self._exercise_public_primitive(rsaObj) - - def test_generate_2arg(self): - """RSA (default implementation) generated key (2 arguments)""" - rsaObj = self.rsa.generate(1024, Random.new().read) - self._check_private_key(rsaObj) - self._exercise_primitive(rsaObj) - pub = rsaObj.public_key() - self._check_public_key(pub) - self._exercise_public_primitive(rsaObj) - - def test_generate_3args(self): - rsaObj = self.rsa.generate(1024, Random.new().read,e=65537) - self._check_private_key(rsaObj) - self._exercise_primitive(rsaObj) - pub = rsaObj.public_key() - self._check_public_key(pub) - self._exercise_public_primitive(rsaObj) - self.assertEqual(65537,rsaObj.e) - - def test_construct_2tuple(self): - """RSA (default implementation) constructed key (2-tuple)""" - pub = self.rsa.construct((self.n, self.e)) - self._check_public_key(pub) - self._check_encryption(pub) - - def test_construct_3tuple(self): - """RSA (default implementation) constructed key (3-tuple)""" - rsaObj = self.rsa.construct((self.n, self.e, self.d)) - self._check_encryption(rsaObj) - self._check_decryption(rsaObj) - - def test_construct_4tuple(self): - """RSA (default implementation) constructed key (4-tuple)""" - rsaObj = self.rsa.construct((self.n, self.e, self.d, self.p)) - self._check_encryption(rsaObj) - self._check_decryption(rsaObj) - - def test_construct_5tuple(self): - """RSA (default implementation) constructed key (5-tuple)""" - rsaObj = self.rsa.construct((self.n, self.e, self.d, self.p, self.q)) - self._check_private_key(rsaObj) - self._check_encryption(rsaObj) - self._check_decryption(rsaObj) - - def test_construct_6tuple(self): - """RSA (default implementation) constructed key (6-tuple)""" - rsaObj = self.rsa.construct((self.n, self.e, self.d, self.p, self.q, self.u)) - self._check_private_key(rsaObj) - self._check_encryption(rsaObj) - self._check_decryption(rsaObj) - - def test_construct_bad_key2(self): - tup = (self.n, 1) - self.assertRaises(ValueError, self.rsa.construct, tup) - - # An even modulus is wrong - tup = (self.n+1, self.e) - self.assertRaises(ValueError, self.rsa.construct, tup) - - def test_construct_bad_key3(self): - tup = (self.n, self.e, self.d+1) - self.assertRaises(ValueError, self.rsa.construct, tup) - - def test_construct_bad_key5(self): - tup = (self.n, self.e, self.d, self.p, self.p) - self.assertRaises(ValueError, self.rsa.construct, tup) - - tup = (self.p*self.p, self.e, self.p, self.p) - self.assertRaises(ValueError, self.rsa.construct, tup) - - tup = (self.p*self.p, 3, self.p, self.q) - self.assertRaises(ValueError, self.rsa.construct, tup) - - def test_construct_bad_key6(self): - tup = (self.n, self.e, self.d, self.p, self.q, 10) - self.assertRaises(ValueError, self.rsa.construct, tup) - - from Crypto.Util.number import inverse - tup = (self.n, self.e, self.d, self.p, self.q, inverse(self.q, self.p)) - self.assertRaises(ValueError, self.rsa.construct, tup) - - def test_factoring(self): - rsaObj = self.rsa.construct([self.n, self.e, self.d]) - self.failUnless(rsaObj.p==self.p or rsaObj.p==self.q) - self.failUnless(rsaObj.q==self.p or rsaObj.q==self.q) - self.failUnless(rsaObj.q*rsaObj.p == self.n) - - self.assertRaises(ValueError, self.rsa.construct, [self.n, self.e, self.n-1]) - - def test_repr(self): - rsaObj = self.rsa.construct((self.n, self.e, self.d, self.p, self.q)) - repr(rsaObj) - - def test_serialization(self): - """RSA keys are unpickable""" - - rsa_key = self.rsa.generate(1024) - self.assertRaises(PicklingError, pickle.dumps, rsa_key) - - def test_raw_rsa_boundary(self): - # The argument of every RSA raw operation (encrypt/decrypt) must be - # non-negative and no larger than the modulus - rsa_obj = self.rsa.generate(1024) - - self.assertRaises(ValueError, rsa_obj._decrypt, rsa_obj.n) - self.assertRaises(ValueError, rsa_obj._encrypt, rsa_obj.n) - - self.assertRaises(ValueError, rsa_obj._decrypt, -1) - self.assertRaises(ValueError, rsa_obj._encrypt, -1) - - def test_size(self): - pub = self.rsa.construct((self.n, self.e)) - self.assertEquals(pub.size_in_bits(), 1024) - self.assertEquals(pub.size_in_bytes(), 128) - - def _check_private_key(self, rsaObj): - from Crypto.Math.Numbers import Integer - - # Check capabilities - self.assertEqual(1, rsaObj.has_private()) - - # Sanity check key data - self.assertEqual(rsaObj.n, rsaObj.p * rsaObj.q) # n = pq - lcm = int(Integer(rsaObj.p-1).lcm(rsaObj.q-1)) - self.assertEqual(1, rsaObj.d * rsaObj.e % lcm) # ed = 1 (mod LCM(p-1, q-1)) - self.assertEqual(1, rsaObj.p * rsaObj.u % rsaObj.q) # pu = 1 (mod q) - self.assertEqual(1, rsaObj.p > 1) # p > 1 - self.assertEqual(1, rsaObj.q > 1) # q > 1 - self.assertEqual(1, rsaObj.e > 1) # e > 1 - self.assertEqual(1, rsaObj.d > 1) # d > 1 - - def _check_public_key(self, rsaObj): - ciphertext = a2b_hex(self.ciphertext) - - # Check capabilities - self.assertEqual(0, rsaObj.has_private()) - - # Check rsaObj.[ne] -> rsaObj.[ne] mapping - self.assertEqual(rsaObj.n, rsaObj.n) - self.assertEqual(rsaObj.e, rsaObj.e) - - # Check that private parameters are all missing - self.assertEqual(0, hasattr(rsaObj, 'd')) - self.assertEqual(0, hasattr(rsaObj, 'p')) - self.assertEqual(0, hasattr(rsaObj, 'q')) - self.assertEqual(0, hasattr(rsaObj, 'u')) - - # Sanity check key data - self.assertEqual(1, rsaObj.e > 1) # e > 1 - - # Public keys should not be able to sign or decrypt - self.assertRaises(TypeError, rsaObj._decrypt, - bytes_to_long(ciphertext)) - - # Check __eq__ and __ne__ - self.assertEqual(rsaObj.public_key() == rsaObj.public_key(),True) # assert_ - self.assertEqual(rsaObj.public_key() != rsaObj.public_key(),False) # failIf - - self.assertEqual(rsaObj.publickey(), rsaObj.public_key()) - - def _exercise_primitive(self, rsaObj): - # Since we're using a randomly-generated key, we can't check the test - # vector, but we can make sure encryption and decryption are inverse - # operations. - ciphertext = bytes_to_long(a2b_hex(self.ciphertext)) - - # Test decryption - plaintext = rsaObj._decrypt(ciphertext) - - # Test encryption (2 arguments) - new_ciphertext2 = rsaObj._encrypt(plaintext) - self.assertEqual(ciphertext, new_ciphertext2) - - def _exercise_public_primitive(self, rsaObj): - plaintext = a2b_hex(self.plaintext) - - # Test encryption (2 arguments) - new_ciphertext2 = rsaObj._encrypt(bytes_to_long(plaintext)) - - def _check_encryption(self, rsaObj): - plaintext = a2b_hex(self.plaintext) - ciphertext = a2b_hex(self.ciphertext) - - # Test encryption - new_ciphertext2 = rsaObj._encrypt(bytes_to_long(plaintext)) - self.assertEqual(bytes_to_long(ciphertext), new_ciphertext2) - - def _check_decryption(self, rsaObj): - plaintext = bytes_to_long(a2b_hex(self.plaintext)) - ciphertext = bytes_to_long(a2b_hex(self.ciphertext)) - - # Test plain decryption - new_plaintext = rsaObj._decrypt(ciphertext) - self.assertEqual(plaintext, new_plaintext) - - -def get_tests(config={}): - tests = [] - tests += list_test_cases(RSATest) - return tests - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') - -# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/Crypto/SelfTest/PublicKey/test_import_DSA.py b/Crypto/SelfTest/PublicKey/test_import_DSA.py deleted file mode 100644 index 2a12ea2..0000000 --- a/Crypto/SelfTest/PublicKey/test_import_DSA.py +++ /dev/null @@ -1,554 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/PublicKey/test_import_DSA.py: Self-test for importing DSA keys -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -import unittest -import re - -from Crypto.PublicKey import DSA -from Crypto.SelfTest.st_common import * -from Crypto.Util.py3compat import * - -from binascii import unhexlify - -class ImportKeyTests(unittest.TestCase): - - y = 92137165128186062214622779787483327510946462589285775188003362705875131352591574106484271700740858696583623951844732128165434284507709057439633739849986759064015013893156866539696757799934634945787496920169462601722830899660681779448742875054459716726855443681559131362852474817534616736104831095601710736729 - p = 162452170958135306109773853318304545923250830605675936228618290525164105310663722368377131295055868997377338797580997938253236213714988311430600065853662861806894003694743806769284131194035848116051021923956699231855223389086646903420682639786976554552864568460372266462812137447840653688476258666833303658691 - q = 988791743931120302950649732173330531512663554851 - g = 85583152299197514738065570254868711517748965097380456700369348466136657764813442044039878840094809620913085570225318356734366886985903212775602770761953571967834823306046501307810937486758039063386311593890777319935391363872375452381836756832784184928202587843258855704771836753434368484556809100537243908232 - x = 540873410045082450874416847965843801027716145253 - - def setUp(self): - - # It is easier to write test vectors in text form, - # and convert them to byte strigs dynamically here - for mname, mvalue in ImportKeyTests.__dict__.items(): - if mname[:4] in ('der_', 'pem_', 'ssh_'): - if mname[:4] == 'der_': - mvalue = unhexlify(tobytes(mvalue)) - mvalue = tobytes(mvalue) - setattr(self, mname, mvalue) - - # 1. SubjectPublicKeyInfo - der_public=\ - '308201b73082012b06072a8648ce3804013082011e02818100e756ee1717f4b6'+\ - '794c7c214724a19763742c45572b4b3f8ff3b44f3be9f44ce039a2757695ec91'+\ - '5697da74ef914fcd1b05660e2419c761d639f45d2d79b802dbd23e7ab8b81b47'+\ - '9a380e1f30932584ba2a0b955032342ebc83cb5ca906e7b0d7cd6fe656cecb4c'+\ - '8b5a77123a8c6750a481e3b06057aff6aa6eba620b832d60c3021500ad32f48c'+\ - 'd3ae0c45a198a61fa4b5e20320763b2302818079dfdc3d614fe635fceb7eaeae'+\ - '3718dc2efefb45282993ac6749dc83c223d8c1887296316b3b0b54466cf444f3'+\ - '4b82e3554d0b90a778faaf1306f025dae6a3e36c7f93dd5bac4052b92370040a'+\ - 'ca70b8d5820599711900efbc961812c355dd9beffe0981da85c5548074b41c56'+\ - 'ae43fd300d89262e4efd89943f99a651b03888038185000281810083352a69a1'+\ - '32f34843d2a0eb995bff4e2f083a73f0049d2c91ea2f0ce43d144abda48199e4'+\ - 'b003c570a8af83303d45105f606c5c48d925a40ed9c2630c2fa4cdbf838539de'+\ - 'b9a29f919085f2046369f627ca84b2cb1e2c7940564b670f963ab1164d4e2ca2'+\ - 'bf6ffd39f12f548928bf4d2d1b5e6980b4f1be4c92a91986fba559' - - def testImportKey1(self): - key_obj = DSA.importKey(self.der_public) - self.failIf(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - - def testExportKey1(self): - tup = (self.y, self.g, self.p, self.q) - key = DSA.construct(tup) - encoded = key.export_key('DER') - self.assertEqual(self.der_public, encoded) - - # 2. - pem_public="""\ ------BEGIN PUBLIC KEY----- -MIIBtzCCASsGByqGSM44BAEwggEeAoGBAOdW7hcX9LZ5THwhRyShl2N0LEVXK0s/ -j/O0Tzvp9EzgOaJ1dpXskVaX2nTvkU/NGwVmDiQZx2HWOfRdLXm4AtvSPnq4uBtH -mjgOHzCTJYS6KguVUDI0LryDy1ypBuew181v5lbOy0yLWncSOoxnUKSB47BgV6/2 -qm66YguDLWDDAhUArTL0jNOuDEWhmKYfpLXiAyB2OyMCgYB539w9YU/mNfzrfq6u -NxjcLv77RSgpk6xnSdyDwiPYwYhyljFrOwtURmz0RPNLguNVTQuQp3j6rxMG8CXa -5qPjbH+T3VusQFK5I3AECspwuNWCBZlxGQDvvJYYEsNV3Zvv/gmB2oXFVIB0tBxW -rkP9MA2JJi5O/YmUP5mmUbA4iAOBhQACgYEAgzUqaaEy80hD0qDrmVv/Ti8IOnPw -BJ0skeovDOQ9FEq9pIGZ5LADxXCor4MwPUUQX2BsXEjZJaQO2cJjDC+kzb+DhTne -uaKfkZCF8gRjafYnyoSyyx4seUBWS2cPljqxFk1OLKK/b/058S9UiSi/TS0bXmmA -tPG+TJKpGYb7pVk= ------END PUBLIC KEY-----""" - - def testImportKey2(self): - for pem in (self.pem_public, tostr(self.pem_public)): - key_obj = DSA.importKey(pem) - self.failIf(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - - def testExportKey2(self): - tup = (self.y, self.g, self.p, self.q) - key = DSA.construct(tup) - encoded = key.export_key('PEM') - self.assertEqual(self.pem_public, encoded) - - # 3. OpenSSL/OpenSSH format - der_private=\ - '308201bb02010002818100e756ee1717f4b6794c7c214724a19763742c45572b'+\ - '4b3f8ff3b44f3be9f44ce039a2757695ec915697da74ef914fcd1b05660e2419'+\ - 'c761d639f45d2d79b802dbd23e7ab8b81b479a380e1f30932584ba2a0b955032'+\ - '342ebc83cb5ca906e7b0d7cd6fe656cecb4c8b5a77123a8c6750a481e3b06057'+\ - 'aff6aa6eba620b832d60c3021500ad32f48cd3ae0c45a198a61fa4b5e2032076'+\ - '3b2302818079dfdc3d614fe635fceb7eaeae3718dc2efefb45282993ac6749dc'+\ - '83c223d8c1887296316b3b0b54466cf444f34b82e3554d0b90a778faaf1306f0'+\ - '25dae6a3e36c7f93dd5bac4052b92370040aca70b8d5820599711900efbc9618'+\ - '12c355dd9beffe0981da85c5548074b41c56ae43fd300d89262e4efd89943f99'+\ - 'a651b038880281810083352a69a132f34843d2a0eb995bff4e2f083a73f0049d'+\ - '2c91ea2f0ce43d144abda48199e4b003c570a8af83303d45105f606c5c48d925'+\ - 'a40ed9c2630c2fa4cdbf838539deb9a29f919085f2046369f627ca84b2cb1e2c'+\ - '7940564b670f963ab1164d4e2ca2bf6ffd39f12f548928bf4d2d1b5e6980b4f1'+\ - 'be4c92a91986fba55902145ebd9a3f0b82069d98420986b314215025756065' - - def testImportKey3(self): - key_obj = DSA.importKey(self.der_private) - self.failUnless(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - self.assertEqual(self.x, key_obj.x) - - def testExportKey3(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - encoded = key.export_key('DER', pkcs8=False) - self.assertEqual(self.der_private, encoded) - - # 4. - pem_private="""\ ------BEGIN DSA PRIVATE KEY----- -MIIBuwIBAAKBgQDnVu4XF/S2eUx8IUckoZdjdCxFVytLP4/ztE876fRM4DmidXaV -7JFWl9p075FPzRsFZg4kGcdh1jn0XS15uALb0j56uLgbR5o4Dh8wkyWEuioLlVAy -NC68g8tcqQbnsNfNb+ZWzstMi1p3EjqMZ1CkgeOwYFev9qpuumILgy1gwwIVAK0y -9IzTrgxFoZimH6S14gMgdjsjAoGAed/cPWFP5jX8636urjcY3C7++0UoKZOsZ0nc -g8Ij2MGIcpYxazsLVEZs9ETzS4LjVU0LkKd4+q8TBvAl2uaj42x/k91brEBSuSNw -BArKcLjVggWZcRkA77yWGBLDVd2b7/4JgdqFxVSAdLQcVq5D/TANiSYuTv2JlD+Z -plGwOIgCgYEAgzUqaaEy80hD0qDrmVv/Ti8IOnPwBJ0skeovDOQ9FEq9pIGZ5LAD -xXCor4MwPUUQX2BsXEjZJaQO2cJjDC+kzb+DhTneuaKfkZCF8gRjafYnyoSyyx4s -eUBWS2cPljqxFk1OLKK/b/058S9UiSi/TS0bXmmAtPG+TJKpGYb7pVkCFF69mj8L -ggadmEIJhrMUIVAldWBl ------END DSA PRIVATE KEY-----""" - - def testImportKey4(self): - for pem in (self.pem_private, tostr(self.pem_private)): - key_obj = DSA.importKey(pem) - self.failUnless(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - self.assertEqual(self.x, key_obj.x) - - def testExportKey4(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - encoded = key.export_key('PEM', pkcs8=False) - self.assertEqual(self.pem_private, encoded) - - # 5. PKCS8 (unencrypted) - der_pkcs8=\ - '3082014a0201003082012b06072a8648ce3804013082011e02818100e756ee17'+\ - '17f4b6794c7c214724a19763742c45572b4b3f8ff3b44f3be9f44ce039a27576'+\ - '95ec915697da74ef914fcd1b05660e2419c761d639f45d2d79b802dbd23e7ab8'+\ - 'b81b479a380e1f30932584ba2a0b955032342ebc83cb5ca906e7b0d7cd6fe656'+\ - 'cecb4c8b5a77123a8c6750a481e3b06057aff6aa6eba620b832d60c3021500ad'+\ - '32f48cd3ae0c45a198a61fa4b5e20320763b2302818079dfdc3d614fe635fceb'+\ - '7eaeae3718dc2efefb45282993ac6749dc83c223d8c1887296316b3b0b54466c'+\ - 'f444f34b82e3554d0b90a778faaf1306f025dae6a3e36c7f93dd5bac4052b923'+\ - '70040aca70b8d5820599711900efbc961812c355dd9beffe0981da85c5548074'+\ - 'b41c56ae43fd300d89262e4efd89943f99a651b03888041602145ebd9a3f0b82'+\ - '069d98420986b314215025756065' - - def testImportKey5(self): - key_obj = DSA.importKey(self.der_pkcs8) - self.failUnless(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - self.assertEqual(self.x, key_obj.x) - - def testExportKey5(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - encoded = key.export_key('DER') - self.assertEqual(self.der_pkcs8, encoded) - encoded = key.export_key('DER', pkcs8=True) - self.assertEqual(self.der_pkcs8, encoded) - - # 6. - pem_pkcs8="""\ ------BEGIN PRIVATE KEY----- -MIIBSgIBADCCASsGByqGSM44BAEwggEeAoGBAOdW7hcX9LZ5THwhRyShl2N0LEVX -K0s/j/O0Tzvp9EzgOaJ1dpXskVaX2nTvkU/NGwVmDiQZx2HWOfRdLXm4AtvSPnq4 -uBtHmjgOHzCTJYS6KguVUDI0LryDy1ypBuew181v5lbOy0yLWncSOoxnUKSB47Bg -V6/2qm66YguDLWDDAhUArTL0jNOuDEWhmKYfpLXiAyB2OyMCgYB539w9YU/mNfzr -fq6uNxjcLv77RSgpk6xnSdyDwiPYwYhyljFrOwtURmz0RPNLguNVTQuQp3j6rxMG -8CXa5qPjbH+T3VusQFK5I3AECspwuNWCBZlxGQDvvJYYEsNV3Zvv/gmB2oXFVIB0 -tBxWrkP9MA2JJi5O/YmUP5mmUbA4iAQWAhRevZo/C4IGnZhCCYazFCFQJXVgZQ== ------END PRIVATE KEY-----""" - - def testImportKey6(self): - for pem in (self.pem_pkcs8, tostr(self.pem_pkcs8)): - key_obj = DSA.importKey(pem) - self.failUnless(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - self.assertEqual(self.x, key_obj.x) - - def testExportKey6(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - encoded = key.export_key('PEM') - self.assertEqual(self.pem_pkcs8, encoded) - encoded = key.export_key('PEM', pkcs8=True) - self.assertEqual(self.pem_pkcs8, encoded) - - # 7. OpenSSH/RFC4253 - ssh_pub="""ssh-dss AAAAB3NzaC1kc3MAAACBAOdW7hcX9LZ5THwhRyShl2N0LEVXK0s/j/O0Tzvp9EzgOaJ1dpXskVaX2nTvkU/NGwVmDiQZx2HWOfRdLXm4AtvSPnq4uBtHmjgOHzCTJYS6KguVUDI0LryDy1ypBuew181v5lbOy0yLWncSOoxnUKSB47BgV6/2qm66YguDLWDDAAAAFQCtMvSM064MRaGYph+kteIDIHY7IwAAAIB539w9YU/mNfzrfq6uNxjcLv77RSgpk6xnSdyDwiPYwYhyljFrOwtURmz0RPNLguNVTQuQp3j6rxMG8CXa5qPjbH+T3VusQFK5I3AECspwuNWCBZlxGQDvvJYYEsNV3Zvv/gmB2oXFVIB0tBxWrkP9MA2JJi5O/YmUP5mmUbA4iAAAAIEAgzUqaaEy80hD0qDrmVv/Ti8IOnPwBJ0skeovDOQ9FEq9pIGZ5LADxXCor4MwPUUQX2BsXEjZJaQO2cJjDC+kzb+DhTneuaKfkZCF8gRjafYnyoSyyx4seUBWS2cPljqxFk1OLKK/b/058S9UiSi/TS0bXmmAtPG+TJKpGYb7pVk=""" - - def testImportKey7(self): - for ssh in (self.ssh_pub, tostr(self.ssh_pub)): - key_obj = DSA.importKey(ssh) - self.failIf(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - - def testExportKey7(self): - tup = (self.y, self.g, self.p, self.q) - key = DSA.construct(tup) - encoded = key.export_key('OpenSSH') - self.assertEqual(self.ssh_pub, encoded) - - # 8. Encrypted OpenSSL/OpenSSH - pem_private_encrypted="""\ ------BEGIN DSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: AES-128-CBC,70B6908939D65E9F2EB999E8729788CE - -4V6GHRDpCrdZ8MBjbyp5AlGUrjvr2Pn2e2zVxy5RBt4FBj9/pa0ae0nnyUPMLSUU -kKyOR0topRYTVRLElm4qVrb5uNZ3hRwfbklr+pSrB7O9eHz9V5sfOQxyODS07JxK -k1OdOs70/ouMXLF9EWfAZOmWUccZKHNblUwg1p1UrZIz5jXw4dUE/zqhvXh6d+iC -ADsICaBCjCrRQJKDp50h3+ndQjkYBKVH+pj8TiQ79U7lAvdp3+iMghQN6YXs9mdI -gFpWw/f97oWM4GHZFqHJ+VSMNFjBiFhAvYV587d7Lk4dhD8sCfbxj42PnfRgUItc -nnPqHxmhMQozBWzYM4mQuo3XbF2WlsNFbOzFVyGhw1Bx1s91qvXBVWJh2ozrW0s6 -HYDV7ZkcTml/4kjA/d+mve6LZ8kuuR1qCiZx6rkffhh1gDN/1Xz3HVvIy/dQ+h9s -5zp7PwUoWbhqp3WCOr156P6gR8qo7OlT6wMh33FSXK/mxikHK136fV2shwTKQVII -rJBvXpj8nACUmi7scKuTWGeUoXa+dwTZVVe+b+L2U1ZM7+h/neTJiXn7u99PFUwu -xVJtxaV37m3aXxtCsPnbBg== ------END DSA PRIVATE KEY-----""" - - def testImportKey8(self): - for pem in (self.pem_private_encrypted, tostr(self.pem_private_encrypted)): - key_obj = DSA.importKey(pem, "PWDTEST") - self.failUnless(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - self.assertEqual(self.x, key_obj.x) - - def testExportKey8(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - encoded = key.export_key('PEM', pkcs8=False, passphrase="PWDTEST") - key = DSA.importKey(encoded, "PWDTEST") - self.assertEqual(self.y, key.y) - self.assertEqual(self.p, key.p) - self.assertEqual(self.q, key.q) - self.assertEqual(self.g, key.g) - self.assertEqual(self.x, key.x) - - # 9. Encrypted PKCS8 - # pbeWithMD5AndDES-CBC - pem_pkcs8_encrypted="""\ ------BEGIN ENCRYPTED PRIVATE KEY----- -MIIBcTAbBgkqhkiG9w0BBQMwDgQI0GC3BJ/jSw8CAggABIIBUHc1cXZpExIE9tC7 -7ryiW+5ihtF2Ekurq3e408GYSAu5smJjN2bvQXmzRFBz8W38K8eMf1sbWroZ4+zn -kZSbb9nSm5kAa8lR2+oF2k+WRswMR/PTC3f/D9STO2X0QxdrzKgIHEcSGSHp5jTx -aVvbkCDHo9vhBTl6S3ogZ48As/MEro76+9igUwJ1jNhIQZPJ7e20QH5qDpQFFJN4 -CKl2ENSEuwGiqBszItFy4dqH0g63ZGZV/xt9wSO9Rd7SK/EbA/dklOxBa5Y/VItM -gnIhs9XDMoGYyn6F023EicNJm6g/bVQk81BTTma4tm+12TKGdYm+QkeZvCOMZylr -Wv67cKwO3cAXt5C3QXMDgYR64XvuaT5h7C0igMp2afSXJlnbHEbFxQVJlv83T4FM -eZ4k+NQDbEL8GiHmFxzDWQAuPPZKJWEEEV2p/To+WOh+kSDHQw== ------END ENCRYPTED PRIVATE KEY-----""" - - def testImportKey9(self): - for pem in (self.pem_pkcs8_encrypted, tostr(self.pem_pkcs8_encrypted)): - key_obj = DSA.importKey(pem, "PWDTEST") - self.failUnless(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - self.assertEqual(self.x, key_obj.x) - - # 10. Encrypted PKCS8 - # pkcs5PBES2 / - # pkcs5PBKDF2 (rounds=1000, salt=D725BF1B6B8239F4) / - # des-EDE3-CBC (iv=27A1C66C42AFEECE) - # - der_pkcs8_encrypted=\ - '30820196304006092a864886f70d01050d3033301b06092a864886f70d01050c'+\ - '300e0408d725bf1b6b8239f4020203e8301406082a864886f70d0307040827a1'+\ - 'c66c42afeece048201505cacfde7bf8edabb3e0d387950dc872662ea7e9b1ed4'+\ - '400d2e7e6186284b64668d8d0328c33a9d9397e6f03df7cb68268b0a06b4e22f'+\ - '7d132821449ecf998a8b696dbc6dd2b19e66d7eb2edfeb4153c1771d49702395'+\ - '4f36072868b5fcccf93413a5ac4b2eb47d4b3f681c6bd67ae363ed776f45ae47'+\ - '174a00098a7c930a50f820b227ddf50f9742d8e950d02586ff2dac0e3c372248'+\ - 'e5f9b6a7a02f4004f20c87913e0f7b52bccc209b95d478256a890b31d4c9adec'+\ - '21a4d157a179a93a3dad06f94f3ce486b46dfa7fc15fd852dd7680bbb2f17478'+\ - '7e71bd8dbaf81eca7518d76c1d26256e95424864ba45ca5d47d7c5a421be02fa'+\ - 'b94ab01e18593f66cf9094eb5c94b9ecf3aa08b854a195cf87612fbe5e96c426'+\ - '2b0d573e52dc71ba3f5e468c601e816c49b7d32c698b22175e89aaef0c443770'+\ - '5ef2f88a116d99d8e2869a4fd09a771b84b49e4ccb79aadcb1c9' - - def testImportKey10(self): - key_obj = DSA.importKey(self.der_pkcs8_encrypted, "PWDTEST") - self.failUnless(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - self.assertEqual(self.x, key_obj.x) - - def testExportKey10(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - randfunc = BytesIO(unhexlify(b("27A1C66C42AFEECE") + b("D725BF1B6B8239F4"))).read - encoded = key.export_key('DER', pkcs8=True, passphrase="PWDTEST", randfunc=randfunc) - self.assertEqual(self.der_pkcs8_encrypted, encoded) - - # ---- - - def testImportError1(self): - self.assertRaises(ValueError, DSA.importKey, self.der_pkcs8_encrypted, "wrongpwd") - - def testExportError2(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - self.assertRaises(ValueError, key.export_key, 'DER', pkcs8=False, passphrase="PWDTEST") - - def test_import_key(self): - """Verify importKey is an alias to import_key""" - - key_obj = DSA.import_key(self.der_public) - self.failIf(key_obj.has_private()) - self.assertEqual(self.y, key_obj.y) - self.assertEqual(self.p, key_obj.p) - self.assertEqual(self.q, key_obj.q) - self.assertEqual(self.g, key_obj.g) - - def test_exportKey(self): - tup = (self.y, self.g, self.p, self.q, self.x) - key = DSA.construct(tup) - self.assertEquals(key.exportKey(), key.export_key()) - - - def test_import_empty(self): - self.assertRaises(ValueError, DSA.import_key, b'') - - -class ImportKeyFromX509Cert(unittest.TestCase): - - def test_x509v1(self): - - # Sample V1 certificate with a 1024 bit DSA key - x509_v1_cert = """ ------BEGIN CERTIFICATE----- -MIIDUjCCArsCAQIwDQYJKoZIhvcNAQEFBQAwfjENMAsGA1UEChMEQWNtZTELMAkG -A1UECxMCUkQxHDAaBgkqhkiG9w0BCQEWDXNwYW1AYWNtZS5vcmcxEzARBgNVBAcT -Ck1ldHJvcG9saXMxETAPBgNVBAgTCE5ldyBZb3JrMQswCQYDVQQGEwJVUzENMAsG -A1UEAxMEdGVzdDAeFw0xNDA3MTEyMDM4NDNaFw0xNzA0MDYyMDM4NDNaME0xCzAJ -BgNVBAYTAlVTMREwDwYDVQQIEwhOZXcgWW9yazENMAsGA1UEChMEQWNtZTELMAkG -A1UECxMCUkQxDzANBgNVBAMTBnBvbGFuZDCCAbYwggErBgcqhkjOOAQBMIIBHgKB -gQDOrN4Ox4+t3T6wKeHfhzArhcrNEFMQ4Ss+4PIKyimDy9Bn64WPkL1B/9dvYIga -23GLu6tVJmXo6EdJnVOHEMhr99EeOwuDWWeP7Awq7RSlKEejokr4BEzMTW/tExSD -cO6/GI7xzh0eTH+VTTPDfyrJMYCkh0rJAfCP+5xrmPNetwIVALtXYOV1yoRrzJ2Q -M5uEjidH6GiZAoGAfUqA1SAm5g5U68SILMVX9l5rq0OpB0waBMpJQ31/R/yXNDqo -c3gGWZTOJFU4IzwNpGhrGNADUByz/lc1SAOAdEJIr0JVrhbGewQjB4pWqoLGbBKz -RoavTNDc/zD7SYa12evWDHADwvlXoeQg+lWop1zS8OqaDC7aLGKpWN3/m8kDgYQA -AoGAKoirPAfcp1rbbl4y2FFAIktfW8f4+T7d2iKSg73aiVfujhNOt1Zz1lfC0NI2 -eonLWO3tAM4XGKf1TLjb5UXngGn40okPsaA81YE6ZIKm20ywjlOY3QkAEdMaLVY3 -9PJvM8RGB9m7pLKxyHfGMfF40MVN4222zKeGp7xhM0CNiCUwDQYJKoZIhvcNAQEF -BQADgYEAfbNZfpYa2KlALEM1FZnwvQDvJHntHz8LdeJ4WM7CXDlKi67wY2HKM30w -s2xej75imkVOFd1kF2d0A8sjfriXLVIt1Hwq9ANZomhu4Edx0xpH8tqdh/bDtnM2 -TmduZNY9OWkb07h0CtWD6Zt8fhRllVsSSrlWd/2or7FXNC5weFQ= ------END CERTIFICATE----- - """.strip() - - # DSA public key as dumped by openssl - y_str = """ -2a:88:ab:3c:07:dc:a7:5a:db:6e:5e:32:d8:51:40: -22:4b:5f:5b:c7:f8:f9:3e:dd:da:22:92:83:bd:da: -89:57:ee:8e:13:4e:b7:56:73:d6:57:c2:d0:d2:36: -7a:89:cb:58:ed:ed:00:ce:17:18:a7:f5:4c:b8:db: -e5:45:e7:80:69:f8:d2:89:0f:b1:a0:3c:d5:81:3a: -64:82:a6:db:4c:b0:8e:53:98:dd:09:00:11:d3:1a: -2d:56:37:f4:f2:6f:33:c4:46:07:d9:bb:a4:b2:b1: -c8:77:c6:31:f1:78:d0:c5:4d:e3:6d:b6:cc:a7:86: -a7:bc:61:33:40:8d:88:25 - """ - p_str = """ -00:ce:ac:de:0e:c7:8f:ad:dd:3e:b0:29:e1:df:87: -30:2b:85:ca:cd:10:53:10:e1:2b:3e:e0:f2:0a:ca: -29:83:cb:d0:67:eb:85:8f:90:bd:41:ff:d7:6f:60: -88:1a:db:71:8b:bb:ab:55:26:65:e8:e8:47:49:9d: -53:87:10:c8:6b:f7:d1:1e:3b:0b:83:59:67:8f:ec: -0c:2a:ed:14:a5:28:47:a3:a2:4a:f8:04:4c:cc:4d: -6f:ed:13:14:83:70:ee:bf:18:8e:f1:ce:1d:1e:4c: -7f:95:4d:33:c3:7f:2a:c9:31:80:a4:87:4a:c9:01: -f0:8f:fb:9c:6b:98:f3:5e:b7 - """ - q_str = """ -00:bb:57:60:e5:75:ca:84:6b:cc:9d:90:33:9b:84: -8e:27:47:e8:68:99 - """ - g_str = """ -7d:4a:80:d5:20:26:e6:0e:54:eb:c4:88:2c:c5:57: -f6:5e:6b:ab:43:a9:07:4c:1a:04:ca:49:43:7d:7f: -47:fc:97:34:3a:a8:73:78:06:59:94:ce:24:55:38: -23:3c:0d:a4:68:6b:18:d0:03:50:1c:b3:fe:57:35: -48:03:80:74:42:48:af:42:55:ae:16:c6:7b:04:23: -07:8a:56:aa:82:c6:6c:12:b3:46:86:af:4c:d0:dc: -ff:30:fb:49:86:b5:d9:eb:d6:0c:70:03:c2:f9:57: -a1:e4:20:fa:55:a8:a7:5c:d2:f0:ea:9a:0c:2e:da: -2c:62:a9:58:dd:ff:9b:c9 - """ - - key = DSA.importKey(x509_v1_cert) - for comp_name in ('y', 'p', 'q', 'g'): - comp_str = locals()[comp_name + "_str"] - comp = int(re.sub("[^0-9a-f]", "", comp_str), 16) - self.assertEqual(getattr(key, comp_name), comp) - self.failIf(key.has_private()) - - def test_x509v3(self): - - # Sample V3 certificate with a 1024 bit DSA key - x509_v3_cert = """ ------BEGIN CERTIFICATE----- -MIIFhjCCA26gAwIBAgIBAzANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEL -MAkGA1UECAwCTUQxEjAQBgNVBAcMCUJhbHRpbW9yZTEQMA4GA1UEAwwHVGVzdCBD -QTEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFtcGxlLmNvbTAeFw0xNDA3MTMyMDUz -MjBaFw0xNzA0MDgyMDUzMjBaMEAxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJNRDES -MBAGA1UEBwwJQmFsdGltb3JlMRAwDgYDVQQDDAdhdXN0cmlhMIIBtjCCASsGByqG -SM44BAEwggEeAoGBALfd8gyEpVPA0ZI69Kp3nyJcu5N0ZZ3K1K9hleQLNqKEcZOh -7a/C2J1TPdmHTLJ0rAwBZ1nWxnARSgRphziGDFspKCYQwYcSMz8KoFgvXbXpuchy -oFACiQ2LqZnc5MakuLQtLcQciSYGYj3zmZdYMoa904F1aDWr+DxQI6DVC3/bAhUA -hqXMCJ6fQK3G2O9S3/CC/yVZXCsCgYBRXROl3R2khX7l10LQjDEgo3B1IzjXU/jP -McMBl6XO+nBJXxr/scbq8Ajiv7LTnGpSjgryHtvfj887kfvo8QbSS3kp3vq5uSqI -ui7E7r3jguWaLj616AG1HWOctXJUjqsiabZwsp2h09gHTzmHEXBOmiARu8xFxKAH -xsuo7onAbwOBhAACgYBylWjWSnKHE8mHx1A5m/0GQx6xnhWIe3+MJAnEhRGxA2J4 -SCsfWU0OwglIQToh1z5uUU9oDi9cYgNPBevOFRnDhc2yaJY6VAYnI+D+6J5IU6Yd -0iaG/iSc4sV4bFr0axcPpse3SN0XaQxiKeSFBfFnoMqL+dd9Gb3QPZSllBcVD6OB -1TCB0jAdBgNVHQ4EFgQUx5wN0Puotv388M9Tp/fsPbZpzAUwHwYDVR0jBBgwFoAU -a0hkif3RMaraiWtsOOZZlLu9wJwwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwSgYD -VR0RBEMwQYILZXhhbXBsZS5jb22CD3d3dy5leGFtcGxlLmNvbYIQbWFpbC5leGFt -cGxlLmNvbYIPZnRwLmV4YW1wbGUuY29tMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NM -IEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQsFAAOCAgEAyWf1TiJI -aNEIA9o/PG8/JiGASTS2/HBVTJbkq03k6NkJVk/GxC1DPziTUJ+CdWlHWcAi1EOW -Ach3QxNDRrVfCOfCMDgElIO1094/reJgdFYG00LRi8QkRJuxANV7YS4tLudhyHJC -kR2lhdMNmEuzWK+s2y+5cLrdm7qdvdENQCcV67uvGPx4sc+EaE7x13SczKjWBtbo -QCs6JTOW+EkPRl4Zo27K4OIZ43/J+GxvwU9QUVH3wPVdbbLNw+QeTFBYMTEcxyc4 -kv50HPBFaithziXBFyvdIs19FjkFzu0Uz/e0zb1+vMzQlJMD94HVOrMnIj5Sb2cL -KKdYXS4uhxFJmdV091Xur5JkYYwEzuaGav7J3zOzYutrIGTgDluLCvA+VQkRcTsy -jZ065SkY/v+38QHp+cmm8WRluupJTs8wYzVp6Fu0iFaaK7ztFmaZmHpiPIfDFjva -aCIgzzT5NweJd/b71A2SyzHXJ14zBXsr1PMylMp2TpHIidhuuNuQL6I0HaollB4M -Z3FsVBMhVDw4Z76qnFPr8mZE2tar33hSlJI/3pS/bBiukuBk8U7VB0X8OqaUnP3C -7b2Z4G8GtqDVcKGMzkvMjT4n9rKd/Le+qHSsQOGO9W/0LB7UDAZSwUsfAPnoBgdS -5t9tIomLCOstByXi+gGZue1TcdCa3Ph4kO0= ------END CERTIFICATE----- - """.strip() - - # DSA public key as dumped by openssl - y_str = """ -72:95:68:d6:4a:72:87:13:c9:87:c7:50:39:9b:fd: -06:43:1e:b1:9e:15:88:7b:7f:8c:24:09:c4:85:11: -b1:03:62:78:48:2b:1f:59:4d:0e:c2:09:48:41:3a: -21:d7:3e:6e:51:4f:68:0e:2f:5c:62:03:4f:05:eb: -ce:15:19:c3:85:cd:b2:68:96:3a:54:06:27:23:e0: -fe:e8:9e:48:53:a6:1d:d2:26:86:fe:24:9c:e2:c5: -78:6c:5a:f4:6b:17:0f:a6:c7:b7:48:dd:17:69:0c: -62:29:e4:85:05:f1:67:a0:ca:8b:f9:d7:7d:19:bd: -d0:3d:94:a5:94:17:15:0f - """ - p_str = """ -00:b7:dd:f2:0c:84:a5:53:c0:d1:92:3a:f4:aa:77: -9f:22:5c:bb:93:74:65:9d:ca:d4:af:61:95:e4:0b: -36:a2:84:71:93:a1:ed:af:c2:d8:9d:53:3d:d9:87: -4c:b2:74:ac:0c:01:67:59:d6:c6:70:11:4a:04:69: -87:38:86:0c:5b:29:28:26:10:c1:87:12:33:3f:0a: -a0:58:2f:5d:b5:e9:b9:c8:72:a0:50:02:89:0d:8b: -a9:99:dc:e4:c6:a4:b8:b4:2d:2d:c4:1c:89:26:06: -62:3d:f3:99:97:58:32:86:bd:d3:81:75:68:35:ab: -f8:3c:50:23:a0:d5:0b:7f:db - """ - q_str = """ -00:86:a5:cc:08:9e:9f:40:ad:c6:d8:ef:52:df:f0: -82:ff:25:59:5c:2b - """ - g_str = """ -51:5d:13:a5:dd:1d:a4:85:7e:e5:d7:42:d0:8c:31: -20:a3:70:75:23:38:d7:53:f8:cf:31:c3:01:97:a5: -ce:fa:70:49:5f:1a:ff:b1:c6:ea:f0:08:e2:bf:b2: -d3:9c:6a:52:8e:0a:f2:1e:db:df:8f:cf:3b:91:fb: -e8:f1:06:d2:4b:79:29:de:fa:b9:b9:2a:88:ba:2e: -c4:ee:bd:e3:82:e5:9a:2e:3e:b5:e8:01:b5:1d:63: -9c:b5:72:54:8e:ab:22:69:b6:70:b2:9d:a1:d3:d8: -07:4f:39:87:11:70:4e:9a:20:11:bb:cc:45:c4:a0: -07:c6:cb:a8:ee:89:c0:6f - """ - - key = DSA.importKey(x509_v3_cert) - for comp_name in ('y', 'p', 'q', 'g'): - comp_str = locals()[comp_name + "_str"] - comp = int(re.sub("[^0-9a-f]", "", comp_str), 16) - self.assertEqual(getattr(key, comp_name), comp) - self.failIf(key.has_private()) - - -if __name__ == '__main__': - unittest.main() - -def get_tests(config={}): - tests = [] - tests += list_test_cases(ImportKeyTests) - tests += list_test_cases(ImportKeyFromX509Cert) - return tests - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') - diff --git a/Crypto/SelfTest/PublicKey/test_import_ECC.py b/Crypto/SelfTest/PublicKey/test_import_ECC.py deleted file mode 100644 index bce8d6f..0000000 --- a/Crypto/SelfTest/PublicKey/test_import_ECC.py +++ /dev/null @@ -1,1346 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2015, Legrandin -# 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 errno -import warnings -import unittest -from binascii import unhexlify - -from Crypto.SelfTest.st_common import list_test_cases -from Crypto.Util.py3compat import bord, tostr, FileNotFoundError -from Crypto.Util.number import bytes_to_long -from Crypto.Hash import SHAKE128 - -from Crypto.PublicKey import ECC - -try: - import pycryptodome_test_vectors # type: ignore - test_vectors_available = True -except ImportError: - test_vectors_available = False - - -class MissingTestVectorException(ValueError): - pass - - -def load_file(file_name, mode="rb"): - results = None - - try: - if not test_vectors_available: - raise FileNotFoundError(errno.ENOENT, - os.strerror(errno.ENOENT), - file_name) - - dir_comps = ("PublicKey", "ECC") - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - with open(full_file_name, mode) as file_in: - results = file_in.read() - - except FileNotFoundError: - warnings.warn("Warning: skipping extended tests for ECC", - UserWarning, - stacklevel=2) - - if results is None: - raise MissingTestVectorException("Missing %s" % file_name) - - return results - - -def compact(lines): - ext = b"".join(lines) - return unhexlify(tostr(ext).replace(" ", "").replace(":", "")) - - -def create_ref_keys_p256(): - key_len = 32 - key_lines = load_file("ecc_p256.txt").splitlines() - private_key_d = bytes_to_long(compact(key_lines[2:5])) - public_key_xy = compact(key_lines[6:11]) - assert bord(public_key_xy[0]) == 4 # Uncompressed - public_key_x = bytes_to_long(public_key_xy[1:key_len+1]) - public_key_y = bytes_to_long(public_key_xy[key_len+1:]) - - return (ECC.construct(curve="P-256", d=private_key_d), - ECC.construct(curve="P-256", point_x=public_key_x, point_y=public_key_y)) - -def create_ref_keys_p384(): - key_len = 48 - key_lines = load_file("ecc_p384.txt").splitlines() - private_key_d = bytes_to_long(compact(key_lines[2:6])) - public_key_xy = compact(key_lines[7:14]) - assert bord(public_key_xy[0]) == 4 # Uncompressed - public_key_x = bytes_to_long(public_key_xy[1:key_len+1]) - public_key_y = bytes_to_long(public_key_xy[key_len+1:]) - - return (ECC.construct(curve="P-384", d=private_key_d), - ECC.construct(curve="P-384", point_x=public_key_x, point_y=public_key_y)) - -def create_ref_keys_p521(): - key_len = 66 - key_lines = load_file("ecc_p521.txt").splitlines() - private_key_d = bytes_to_long(compact(key_lines[2:7])) - public_key_xy = compact(key_lines[8:17]) - assert bord(public_key_xy[0]) == 4 # Uncompressed - public_key_x = bytes_to_long(public_key_xy[1:key_len+1]) - public_key_y = bytes_to_long(public_key_xy[key_len+1:]) - - return (ECC.construct(curve="P-521", d=private_key_d), - ECC.construct(curve="P-521", point_x=public_key_x, point_y=public_key_y)) - -# Create reference key pair -# ref_private, ref_public = create_ref_keys_p521() - -def get_fixed_prng(): - return SHAKE128.new().update(b"SEED").read - - -class TestImport(unittest.TestCase): - - def test_empty(self): - self.assertRaises(ValueError, ECC.import_key, b"") - - -class TestImport_P256(unittest.TestCase): - - def __init__(self, *args, **kwargs): - super(TestImport_P256, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p256() - - def test_import_public_der(self): - key_file = load_file("ecc_p256_public.der") - - key = ECC._import_subjectPublicKeyInfo(key_file) - self.assertEqual(self.ref_public, key) - - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) - - def test_import_private_der(self): - key_file = load_file("ecc_p256_private.der") - - key = ECC._import_private_der(key_file, None) - self.assertEqual(self.ref_private, key) - - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) - - def test_import_private_pkcs8_clear(self): - key_file = load_file("ecc_p256_private_p8_clear.der") - - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) - - def test_import_private_pkcs8_in_pem_clear(self): - key_file = load_file("ecc_p256_private_p8_clear.pem") - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) - - def test_import_private_pkcs8_encrypted_1(self): - key_file = load_file("ecc_p256_private_p8.der") - - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) - - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) - - def test_import_private_pkcs8_encrypted_2(self): - key_file = load_file("ecc_p256_private_p8.pem") - - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) - - def test_import_x509_der(self): - key_file = load_file("ecc_p256_x509.der") - - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) - - def test_import_public_pem(self): - key_file = load_file("ecc_p256_public.pem") - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) - - def test_import_private_pem(self): - key_file = load_file("ecc_p256_private.pem") - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) - - def test_import_private_pem_with_ecparams(self): - key_file = load_file("ecc_p256_private_ecparams.pem") - key = ECC.import_key(key_file) - # We just check if the import succeeds - - def test_import_private_pem_encrypted(self): - for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": - key_file = load_file("ecc_p256_private_enc_%s.pem" % algo) - - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) - - key = ECC.import_key(tostr(key_file), b"secret") - self.assertEqual(self.ref_private, key) - - def test_import_x509_pem(self): - key_file = load_file("ecc_p256_x509.pem") - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) - - def test_import_openssh_public(self): - key_file = load_file("ecc_p256_public_openssh.txt") - - key = ECC._import_openssh_public(key_file) - self.assertEqual(self.ref_public, key) - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) - - def test_import_openssh_private_clear(self): - key_file = load_file("ecc_p256_private_openssh.pem") - key_file_old = load_file("ecc_p256_private_openssh_old.pem") - - key = ECC.import_key(key_file) - key_old = ECC.import_key(key_file_old) - self.assertEqual(key, key_old) - - def test_import_openssh_private_password(self): - key_file = load_file("ecc_p256_private_openssh_pwd.pem") - key_file_old = load_file("ecc_p256_private_openssh_pwd_old.pem") - - key = ECC.import_key(key_file, b"password") - key_old = ECC.import_key(key_file_old) - self.assertEqual(key, key_old) - - -class TestImport_P384(unittest.TestCase): - - def __init__(self, *args, **kwargs): - super(TestImport_P384, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p384() - - def test_import_public_der(self): - key_file = load_file("ecc_p384_public.der") - - key = ECC._import_subjectPublicKeyInfo(key_file) - self.assertEqual(self.ref_public, key) - - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) - - def test_import_private_der(self): - key_file = load_file("ecc_p384_private.der") - - key = ECC._import_private_der(key_file, None) - self.assertEqual(self.ref_private, key) - - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) - - def test_import_private_pkcs8_clear(self): - key_file = load_file("ecc_p384_private_p8_clear.der") - - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) - - def test_import_private_pkcs8_in_pem_clear(self): - key_file = load_file("ecc_p384_private_p8_clear.pem") - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) - - def test_import_private_pkcs8_encrypted_1(self): - key_file = load_file("ecc_p384_private_p8.der") - - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) - - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) - - def test_import_private_pkcs8_encrypted_2(self): - key_file = load_file("ecc_p384_private_p8.pem") - - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) - - def test_import_x509_der(self): - key_file = load_file("ecc_p384_x509.der") - - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) - - def test_import_public_pem(self): - key_file = load_file("ecc_p384_public.pem") - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) - - def test_import_private_pem(self): - key_file = load_file("ecc_p384_private.pem") - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) - - def test_import_private_pem_encrypted(self): - for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": - key_file = load_file("ecc_p384_private_enc_%s.pem" % algo) - - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) - - key = ECC.import_key(tostr(key_file), b"secret") - self.assertEqual(self.ref_private, key) - - def test_import_x509_pem(self): - key_file = load_file("ecc_p384_x509.pem") - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) - - def test_import_openssh_public(self): - key_file = load_file("ecc_p384_public_openssh.txt") - - key = ECC._import_openssh_public(key_file) - self.assertEqual(self.ref_public, key) - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) - - def test_import_openssh_private_clear(self): - key_file = load_file("ecc_p384_private_openssh.pem") - key_file_old = load_file("ecc_p384_private_openssh_old.pem") - - key = ECC.import_key(key_file) - key_old = ECC.import_key(key_file_old) - self.assertEqual(key, key_old) - - def test_import_openssh_private_password(self): - key_file = load_file("ecc_p384_private_openssh_pwd.pem") - key_file_old = load_file("ecc_p384_private_openssh_pwd_old.pem") - - key = ECC.import_key(key_file, b"password") - key_old = ECC.import_key(key_file_old) - self.assertEqual(key, key_old) - - -class TestImport_P521(unittest.TestCase): - - def __init__(self, *args, **kwargs): - super(TestImport_P521, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p521() - - def test_import_public_der(self): - key_file = load_file("ecc_p521_public.der") - - key = ECC._import_subjectPublicKeyInfo(key_file) - self.assertEqual(self.ref_public, key) - - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) - - def test_import_private_der(self): - key_file = load_file("ecc_p521_private.der") - - key = ECC._import_private_der(key_file, None) - self.assertEqual(self.ref_private, key) - - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) - - def test_import_private_pkcs8_clear(self): - key_file = load_file("ecc_p521_private_p8_clear.der") - - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_private, key) - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) - - def test_import_private_pkcs8_in_pem_clear(self): - key_file = load_file("ecc_p521_private_p8_clear.pem") - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) - - def test_import_private_pkcs8_encrypted_1(self): - key_file = load_file("ecc_p521_private_p8.der") - - key = ECC._import_der(key_file, "secret") - self.assertEqual(self.ref_private, key) - - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) - - def test_import_private_pkcs8_encrypted_2(self): - key_file = load_file("ecc_p521_private_p8.pem") - - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) - - def test_import_x509_der(self): - key_file = load_file("ecc_p521_x509.der") - - key = ECC._import_der(key_file, None) - self.assertEqual(self.ref_public, key) - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) - - def test_import_public_pem(self): - key_file = load_file("ecc_p521_public.pem") - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) - - def test_import_private_pem(self): - key_file = load_file("ecc_p521_private.pem") - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_private, key) - - def test_import_private_pem_encrypted(self): - for algo in "des3", "aes128", "aes192", "aes256", "aes256_gcm": - key_file = load_file("ecc_p521_private_enc_%s.pem" % algo) - - key = ECC.import_key(key_file, "secret") - self.assertEqual(self.ref_private, key) - - key = ECC.import_key(tostr(key_file), b"secret") - self.assertEqual(self.ref_private, key) - - def test_import_x509_pem(self): - key_file = load_file("ecc_p521_x509.pem") - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) - - def test_import_openssh_public(self): - key_file = load_file("ecc_p521_public_openssh.txt") - - key = ECC._import_openssh_public(key_file) - self.assertEqual(self.ref_public, key) - - key = ECC.import_key(key_file) - self.assertEqual(self.ref_public, key) - - def test_import_openssh_private_clear(self): - key_file = load_file("ecc_p521_private_openssh.pem") - key_file_old = load_file("ecc_p521_private_openssh_old.pem") - - key = ECC.import_key(key_file) - key_old = ECC.import_key(key_file_old) - self.assertEqual(key, key_old) - - def test_import_openssh_private_password(self): - key_file = load_file("ecc_p521_private_openssh_pwd.pem") - key_file_old = load_file("ecc_p521_private_openssh_pwd_old.pem") - - key = ECC.import_key(key_file, b"password") - key_old = ECC.import_key(key_file_old) - self.assertEqual(key, key_old) - - -class TestExport_P256(unittest.TestCase): - - def __init__(self, *args, **kwargs): - super(TestExport_P256, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p256() - - def test_export_public_der_uncompressed(self): - key_file = load_file("ecc_p256_public.der") - - encoded = self.ref_public._export_subjectPublicKeyInfo(False) - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_public_der_compressed(self): - key_file = load_file("ecc_p256_public.der") - pub_key = ECC.import_key(key_file) - key_file_compressed = pub_key.export_key(format="DER", compress=True) - - key_file_compressed_ref = load_file("ecc_p256_public_compressed.der") - self.assertEqual(key_file_compressed, key_file_compressed_ref) - - def test_export_private_der(self): - key_file = load_file("ecc_p256_private.der") - - encoded = self.ref_private._export_private_der() - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) - self.assertEqual(key_file, encoded) - - def test_export_private_pkcs8_clear(self): - key_file = load_file("ecc_p256_private_p8_clear.der") - - encoded = self.ref_private._export_pkcs8() - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="DER") - self.assertEqual(key_file, encoded) - - def test_export_private_pkcs8_encrypted(self): - encoded = self.ref_private._export_pkcs8(passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) - - decoded = ECC._import_pkcs8(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_export_public_pem_uncompressed(self): - key_file = load_file("ecc_p256_public.pem", "rt").strip() - - encoded = self.ref_private._export_public_pem(False) - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_public.export_key(format="PEM") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="PEM", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_public_pem_compressed(self): - key_file = load_file("ecc_p256_public.pem", "rt").strip() - pub_key = ECC.import_key(key_file) - - key_file_compressed = pub_key.export_key(format="PEM", compress=True) - key_file_compressed_ref = load_file("ecc_p256_public_compressed.pem", "rt").strip() - - self.assertEqual(key_file_compressed, key_file_compressed_ref) - - def test_export_private_pem_clear(self): - key_file = load_file("ecc_p256_private.pem", "rt").strip() - - encoded = self.ref_private._export_private_pem(None) - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) - self.assertEqual(key_file, encoded) - - def test_export_private_pem_encrypted(self): - encoded = self.ref_private._export_private_pem(passphrase=b"secret") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) - - assert "EC PRIVATE KEY" in encoded - - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - use_pkcs8=False) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_export_private_pkcs8_and_pem_1(self): - # PKCS8 inside PEM with both unencrypted - key_file = load_file("ecc_p256_private_p8_clear.pem", "rt").strip() - - encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="PEM") - self.assertEqual(key_file, encoded) - - def test_export_private_pkcs8_and_pem_2(self): - # PKCS8 inside PEM with PKCS8 encryption - encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem("secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) - - assert "ENCRYPTED PRIVATE KEY" in encoded - - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_export_openssh_uncompressed(self): - key_file = load_file("ecc_p256_public_openssh.txt", "rt") - - encoded = self.ref_public._export_openssh(False) - self.assertEquals(key_file, encoded) - - # --- - - encoded = self.ref_public.export_key(format="OpenSSH") - self.assertEquals(key_file, encoded) - - encoded = self.ref_public.export_key(format="OpenSSH", compress=False) - self.assertEquals(key_file, encoded) - - def test_export_openssh_compressed(self): - key_file = load_file("ecc_p256_public_openssh.txt", "rt") - pub_key = ECC.import_key(key_file) - - key_file_compressed = pub_key.export_key(format="OpenSSH", compress=True) - assert len(key_file) > len(key_file_compressed) - self.assertEquals(pub_key, ECC.import_key(key_file_compressed)) - - def test_prng(self): - # Test that password-protected containers use the provided PRNG - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEquals(encoded1, encoded2) - - # --- - - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - self.assertEquals(encoded1, encoded2) - - def test_byte_or_string_passphrase(self): - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase=b"secret", - randfunc=get_fixed_prng()) - self.assertEquals(encoded1, encoded2) - - def test_error_params1(self): - # Unknown format - self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") - - # Missing 'protection' parameter when PKCS#8 is used - self.ref_private.export_key(format="PEM", passphrase="secret", - use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="secret") - - # DER format but no PKCS#8 - self.assertRaises(ValueError, self.ref_private.export_key, format="DER", - passphrase="secret", - use_pkcs8=False, - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # Incorrect parameters for public keys - self.assertRaises(ValueError, self.ref_public.export_key, format="DER", - use_pkcs8=False) - - # Empty password - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # No private keys with OpenSSH - self.assertRaises(ValueError, self.ref_private.export_key, format="OpenSSH", - passphrase="secret") - - def test_unsupported_curve(self): - - # openssl ecparam -name secp224r1 -genkey -noout -out strange-curve.pem -conv_form uncompressed - curve = """-----BEGIN EC PRIVATE KEY----- -MGgCAQEEHEi7xTHW+5oT8wgpjoEKV7uwMuY8rt2YUZe4j1SgBwYFK4EEACGhPAM6 -AATJgfOG+Bnki8robpNM8MtArji43GU9up4B0x9sVhqB+fZP+hXgV9ITN7YX4E/k -gVnJp9EBND/tHQ== ------END EC PRIVATE KEY-----""" - - from Crypto.PublicKey.ECC import UnsupportedEccFeature - try: - ECC.import_key(curve) - except UnsupportedEccFeature as uef: - assert("1.3.132.0.33" in str(uef)) - else: - assert(False) - - def test_compressed_curve(self): - - # Compressed P-256 curve (Y-point is even) - pem1 = """-----BEGIN EC PRIVATE KEY----- - MFcCAQEEIHTuc09jC51xXomV6MVCDN+DpAAvSmaJWZPTEHM6D5H1oAoGCCqGSM49 - AwEHoSQDIgACWFuGbHe8yJ43rir7PMTE9w8vHz0BSpXHq90Xi7/s+a0= - -----END EC PRIVATE KEY-----""" - - # Compressed P-256 curve (Y-point is odd) - pem2 = """-----BEGIN EC PRIVATE KEY----- - MFcCAQEEIFggiPN9SQP+FAPTCPp08fRUz7rHp2qNBRcBJ1DXhb3ZoAoGCCqGSM49 - AwEHoSQDIgADLpph1trTIlVfa8NJvlMUPyWvL+wP+pW3BJITUL/wj9A= - -----END EC PRIVATE KEY-----""" - - key1 = ECC.import_key(pem1) - low16 = int(key1.pointQ.y % 65536) - self.assertEqual(low16, 0xA6FC) - - key2 = ECC.import_key(pem2) - low16 = int(key2.pointQ.y % 65536) - self.assertEqual(low16, 0x6E57) - - -class TestExport_P384(unittest.TestCase): - - def __init__(self, *args, **kwargs): - super(TestExport_P384, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p384() - - def test_export_public_der_uncompressed(self): - key_file = load_file("ecc_p384_public.der") - - encoded = self.ref_public._export_subjectPublicKeyInfo(False) - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_public_der_compressed(self): - key_file = load_file("ecc_p384_public.der") - pub_key = ECC.import_key(key_file) - key_file_compressed = pub_key.export_key(format="DER", compress=True) - - key_file_compressed_ref = load_file("ecc_p384_public_compressed.der") - self.assertEqual(key_file_compressed, key_file_compressed_ref) - - def test_export_private_der(self): - key_file = load_file("ecc_p384_private.der") - - encoded = self.ref_private._export_private_der() - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) - self.assertEqual(key_file, encoded) - - def test_export_private_pkcs8_clear(self): - key_file = load_file("ecc_p384_private_p8_clear.der") - - encoded = self.ref_private._export_pkcs8() - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="DER") - self.assertEqual(key_file, encoded) - - def test_export_private_pkcs8_encrypted(self): - encoded = self.ref_private._export_pkcs8(passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) - - decoded = ECC._import_pkcs8(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_export_public_pem_uncompressed(self): - key_file = load_file("ecc_p384_public.pem", "rt").strip() - - encoded = self.ref_private._export_public_pem(False) - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_public.export_key(format="PEM") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="PEM", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_public_pem_compressed(self): - key_file = load_file("ecc_p384_public.pem", "rt").strip() - pub_key = ECC.import_key(key_file) - - key_file_compressed = pub_key.export_key(format="PEM", compress=True) - key_file_compressed_ref = load_file("ecc_p384_public_compressed.pem", "rt").strip() - - self.assertEqual(key_file_compressed, key_file_compressed_ref) - - def test_export_private_pem_clear(self): - key_file = load_file("ecc_p384_private.pem", "rt").strip() - - encoded = self.ref_private._export_private_pem(None) - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) - self.assertEqual(key_file, encoded) - - def test_export_private_pem_encrypted(self): - encoded = self.ref_private._export_private_pem(passphrase=b"secret") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) - - assert "EC PRIVATE KEY" in encoded - - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - use_pkcs8=False) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_export_private_pkcs8_and_pem_1(self): - # PKCS8 inside PEM with both unencrypted - key_file = load_file("ecc_p384_private_p8_clear.pem", "rt").strip() - - encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="PEM") - self.assertEqual(key_file, encoded) - - def test_export_private_pkcs8_and_pem_2(self): - # PKCS8 inside PEM with PKCS8 encryption - encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem("secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) - - assert "ENCRYPTED PRIVATE KEY" in encoded - - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_export_openssh_uncompressed(self): - key_file = load_file("ecc_p384_public_openssh.txt", "rt") - - encoded = self.ref_public._export_openssh(False) - self.assertEquals(key_file, encoded) - - # --- - - encoded = self.ref_public.export_key(format="OpenSSH") - self.assertEquals(key_file, encoded) - - encoded = self.ref_public.export_key(format="OpenSSH", compress=False) - self.assertEquals(key_file, encoded) - - def test_export_openssh_compressed(self): - key_file = load_file("ecc_p384_public_openssh.txt", "rt") - pub_key = ECC.import_key(key_file) - - key_file_compressed = pub_key.export_key(format="OpenSSH", compress=True) - assert len(key_file) > len(key_file_compressed) - self.assertEquals(pub_key, ECC.import_key(key_file_compressed)) - - def test_prng(self): - # Test that password-protected containers use the provided PRNG - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEquals(encoded1, encoded2) - - # --- - - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - self.assertEquals(encoded1, encoded2) - - def test_byte_or_string_passphrase(self): - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase=b"secret", - randfunc=get_fixed_prng()) - self.assertEquals(encoded1, encoded2) - - def test_error_params1(self): - # Unknown format - self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") - - # Missing 'protection' parameter when PKCS#8 is used - self.ref_private.export_key(format="PEM", passphrase="secret", - use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="secret") - - # DER format but no PKCS#8 - self.assertRaises(ValueError, self.ref_private.export_key, format="DER", - passphrase="secret", - use_pkcs8=False, - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # Incorrect parameters for public keys - self.assertRaises(ValueError, self.ref_public.export_key, format="DER", - use_pkcs8=False) - - # Empty password - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # No private keys with OpenSSH - self.assertRaises(ValueError, self.ref_private.export_key, format="OpenSSH", - passphrase="secret") - - def test_compressed_curve(self): - - # Compressed P-384 curve (Y-point is even) - # openssl ecparam -name secp384p1 -genkey -noout -conv_form compressed -out /tmp/a.pem - # openssl ec -in /tmp/a.pem -text -noout - pem1 = """-----BEGIN EC PRIVATE KEY----- -MIGkAgEBBDAM0lEIhvXuekK2SWtdbgOcZtBaxa9TxfpO/GcDFZLCJ3JVXaTgwken -QT+C+XLtD6WgBwYFK4EEACKhZANiAATs0kZMhFDu8DoBC21jrSDPyAUn4aXZ/DM4 -ylhDfWmb4LEbeszXceIzfhIUaaGs5y1xXaqf5KXTiAAYx2pKUzAAM9lcGUHCGKJG -k4AgUmVJON29XoUilcFrzjDmuye3B6Q= ------END EC PRIVATE KEY-----""" - - # Compressed P-384 curve (Y-point is odd) - pem2 = """-----BEGIN EC PRIVATE KEY----- -MIGkAgEBBDDHPFTslYLltE16fHdSDTtE/2HTmd3M8mqy5MttAm4wZ833KXiGS9oe -kFdx9sNV0KygBwYFK4EEACKhZANiAASLIE5RqVMtNhtBH/u/p/ifqOAlKnK/+RrQ -YC46ZRsnKNayw3wATdPjgja7L/DSII3nZK0G6KOOVwJBznT/e+zudUJYhZKaBLRx -/bgXyxUtYClOXxb1Y/5N7txLstYRyP0= ------END EC PRIVATE KEY-----""" - - key1 = ECC.import_key(pem1) - low16 = int(key1.pointQ.y % 65536) - self.assertEqual(low16, 0x07a4) - - key2 = ECC.import_key(pem2) - low16 = int(key2.pointQ.y % 65536) - self.assertEqual(low16, 0xc8fd) - - -class TestExport_P521(unittest.TestCase): - - def __init__(self, *args, **kwargs): - super(TestExport_P521, self).__init__(*args, **kwargs) - self.ref_private, self.ref_public = create_ref_keys_p521() - - def test_export_public_der_uncompressed(self): - key_file = load_file("ecc_p521_public.der") - - encoded = self.ref_public._export_subjectPublicKeyInfo(False) - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="DER", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_public_der_compressed(self): - key_file = load_file("ecc_p521_public.der") - pub_key = ECC.import_key(key_file) - key_file_compressed = pub_key.export_key(format="DER", compress=True) - - key_file_compressed_ref = load_file("ecc_p521_public_compressed.der") - self.assertEqual(key_file_compressed, key_file_compressed_ref) - - def test_export_private_der(self): - key_file = load_file("ecc_p521_private.der") - - encoded = self.ref_private._export_private_der() - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", use_pkcs8=False) - self.assertEqual(key_file, encoded) - - def test_export_private_pkcs8_clear(self): - key_file = load_file("ecc_p521_private_p8_clear.der") - - encoded = self.ref_private._export_pkcs8() - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="DER") - self.assertEqual(key_file, encoded) - - def test_export_private_pkcs8_encrypted(self): - encoded = self.ref_private._export_pkcs8(passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None) - - decoded = ECC._import_pkcs8(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="DER", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_export_public_pem_uncompressed(self): - key_file = load_file("ecc_p521_public.pem", "rt").strip() - - encoded = self.ref_private._export_public_pem(False) - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_public.export_key(format="PEM") - self.assertEqual(key_file, encoded) - - encoded = self.ref_public.export_key(format="PEM", compress=False) - self.assertEqual(key_file, encoded) - - def test_export_public_pem_compressed(self): - key_file = load_file("ecc_p521_public.pem", "rt").strip() - pub_key = ECC.import_key(key_file) - - key_file_compressed = pub_key.export_key(format="PEM", compress=True) - key_file_compressed_ref = load_file("ecc_p521_public_compressed.pem", "rt").strip() - - self.assertEqual(key_file_compressed, key_file_compressed_ref) - - def test_export_private_pem_clear(self): - key_file = load_file("ecc_p521_private.pem", "rt").strip() - - encoded = self.ref_private._export_private_pem(None) - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="PEM", use_pkcs8=False) - self.assertEqual(key_file, encoded) - - def test_export_private_pem_encrypted(self): - encoded = self.ref_private._export_private_pem(passphrase=b"secret") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) - - assert "EC PRIVATE KEY" in encoded - - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - use_pkcs8=False) - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_export_private_pkcs8_and_pem_1(self): - # PKCS8 inside PEM with both unencrypted - key_file = load_file("ecc_p521_private_p8_clear.pem", "rt").strip() - - encoded = self.ref_private._export_private_clear_pkcs8_in_clear_pem() - self.assertEqual(key_file, encoded) - - # --- - - encoded = self.ref_private.export_key(format="PEM") - self.assertEqual(key_file, encoded) - - def test_export_private_pkcs8_and_pem_2(self): - # PKCS8 inside PEM with PKCS8 encryption - encoded = self.ref_private._export_private_encrypted_pkcs8_in_clear_pem("secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # This should prove that the output is password-protected - self.assertRaises(ValueError, ECC.import_key, encoded) - - assert "ENCRYPTED PRIVATE KEY" in encoded - - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - # --- - - encoded = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - decoded = ECC.import_key(encoded, "secret") - self.assertEqual(self.ref_private, decoded) - - def test_export_openssh_uncompressed(self): - key_file = load_file("ecc_p521_public_openssh.txt", "rt") - - encoded = self.ref_public._export_openssh(False) - self.assertEquals(key_file, encoded) - - # --- - - encoded = self.ref_public.export_key(format="OpenSSH") - self.assertEquals(key_file, encoded) - - encoded = self.ref_public.export_key(format="OpenSSH", compress=False) - self.assertEquals(key_file, encoded) - - def test_export_openssh_compressed(self): - key_file = load_file("ecc_p521_public_openssh.txt", "rt") - pub_key = ECC.import_key(key_file) - - key_file_compressed = pub_key.export_key(format="OpenSSH", compress=True) - assert len(key_file) > len(key_file_compressed) - self.assertEquals(pub_key, ECC.import_key(key_file_compressed)) - - def test_prng(self): - # Test that password-protected containers use the provided PRNG - encoded1 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - passphrase="secret", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC", - randfunc=get_fixed_prng()) - self.assertEquals(encoded1, encoded2) - - # --- - - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - self.assertEquals(encoded1, encoded2) - - def test_byte_or_string_passphrase(self): - encoded1 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase="secret", - randfunc=get_fixed_prng()) - encoded2 = self.ref_private.export_key(format="PEM", - use_pkcs8=False, - passphrase=b"secret", - randfunc=get_fixed_prng()) - self.assertEquals(encoded1, encoded2) - - def test_error_params1(self): - # Unknown format - self.assertRaises(ValueError, self.ref_private.export_key, format="XXX") - - # Missing 'protection' parameter when PKCS#8 is used - self.ref_private.export_key(format="PEM", passphrase="secret", - use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="secret") - - # DER format but no PKCS#8 - self.assertRaises(ValueError, self.ref_private.export_key, format="DER", - passphrase="secret", - use_pkcs8=False, - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # Incorrect parameters for public keys - self.assertRaises(ValueError, self.ref_public.export_key, format="DER", - use_pkcs8=False) - - # Empty password - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", use_pkcs8=False) - self.assertRaises(ValueError, self.ref_private.export_key, format="PEM", - passphrase="", - protection="PBKDF2WithHMAC-SHA1AndAES128-CBC") - - # No private keys with OpenSSH - self.assertRaises(ValueError, self.ref_private.export_key, format="OpenSSH", - passphrase="secret") - - def test_compressed_curve(self): - - # Compressed P-521 curve (Y-point is even) - # openssl ecparam -name secp521r1 -genkey -noout -conv_form compressed -out /tmp/a.pem - # openssl ec -in /tmp/a.pem -text -noout - pem1 = """-----BEGIN EC PRIVATE KEY----- -MIHcAgEBBEIAnm1CEjVjvNfXEN730p+D6su5l+mOztdc5XmTEoti+s2R4GQ4mAv3 -0zYLvyklvOHw0+yy8d0cyGEJGb8T3ZVKmg2gBwYFK4EEACOhgYkDgYYABAHzjTI1 -ckxQ3Togi0LAxiG0PucdBBBs5oIy3df95xv6SInp70z+4qQ2EltEmdNMssH8eOrl -M5CYdZ6nbcHMVaJUvQEzTrYxvFjOgJiOd+E9eBWbLkbMNqsh1UKVO6HbMbW0ohCI -uGxO8tM6r3w89/qzpG2SvFM/fvv3mIR30wSZDD84qA== ------END EC PRIVATE KEY-----""" - - # Compressed P-521 curve (Y-point is odd) - pem2 = """-----BEGIN EC PRIVATE KEY----- -MIHcAgEBBEIB84OfhJluLBRLn3+cC/RQ37C2SfQVP/t0gQK2tCsTf5avRcWYRrOJ -PmX9lNnkC0Hobd75QFRmdxrB0Wd1/M4jZOWgBwYFK4EEACOhgYkDgYYABAAMZcdJ -1YLCGHt3bHCEzdidVy6+brlJIbv1aQ9fPQLF7WKNv4c8w3H8d5a2+SDZilBOsk5c -6cNJDMz2ExWQvxl4CwDJtJGt1+LHVKFGy73NANqVxMbRu+2F8lOxkNp/ziFTbVyV -vv6oYkMIIi7r5oQWAiQDrR2mlrrFDL9V7GH/r8SWQw== ------END EC PRIVATE KEY-----""" - - key1 = ECC.import_key(pem1) - low16 = int(key1.pointQ.y % 65536) - self.assertEqual(low16, 0x38a8) - - key2 = ECC.import_key(pem2) - low16 = int(key2.pointQ.y % 65536) - self.assertEqual(low16, 0x9643) - - -def get_tests(config={}): - tests = [] - tests += list_test_cases(TestImport) - try: - tests += list_test_cases(TestImport_P256) - tests += list_test_cases(TestImport_P384) - tests += list_test_cases(TestImport_P521) - tests += list_test_cases(TestExport_P256) - tests += list_test_cases(TestExport_P384) - tests += list_test_cases(TestExport_P521) - except MissingTestVectorException: - pass - return tests - - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/PublicKey/test_import_RSA.py b/Crypto/SelfTest/PublicKey/test_import_RSA.py deleted file mode 100644 index a2963c6..0000000 --- a/Crypto/SelfTest/PublicKey/test_import_RSA.py +++ /dev/null @@ -1,585 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/PublicKey/test_importKey.py: Self-test for importing RSA keys -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -import os -import re -import errno -import warnings -import unittest - -from Crypto.PublicKey import RSA -from Crypto.SelfTest.st_common import a2b_hex, list_test_cases -from Crypto.Util.py3compat import b, tostr, FileNotFoundError -from Crypto.Util.number import inverse -from Crypto.Util import asn1 - -try: - import pycryptodome_test_vectors # type: ignore - test_vectors_available = True -except ImportError: - test_vectors_available = False - - -def load_file(file_name, mode="rb"): - results = None - - try: - if not test_vectors_available: - raise FileNotFoundError(errno.ENOENT, - os.strerror(errno.ENOENT), - file_name) - - dir_comps = ("PublicKey", "RSA") - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - with open(full_file_name, mode) as file_in: - results = file_in.read() - - except FileNotFoundError: - warnings.warn("Warning: skipping extended tests for RSA", - UserWarning, - stacklevel=2) - - return results - - -def der2pem(der, text='PUBLIC'): - import binascii - chunks = [binascii.b2a_base64(der[i:i+48]) for i in range(0, len(der), 48)] - pem = b('-----BEGIN %s KEY-----\n' % text) - pem += b('').join(chunks) - pem += b('-----END %s KEY-----' % text) - return pem - - -class ImportKeyTests(unittest.TestCase): - # 512-bit RSA key generated with openssl - rsaKeyPEM = u'''-----BEGIN RSA PRIVATE KEY----- -MIIBOwIBAAJBAL8eJ5AKoIsjURpcEoGubZMxLD7+kT+TLr7UkvEtFrRhDDKMtuII -q19FrL4pUIMymPMSLBn3hJLe30Dw48GQM4UCAwEAAQJACUSDEp8RTe32ftq8IwG8 -Wojl5mAd1wFiIOrZ/Uv8b963WJOJiuQcVN29vxU5+My9GPZ7RA3hrDBEAoHUDPrI -OQIhAPIPLz4dphiD9imAkivY31Rc5AfHJiQRA7XixTcjEkojAiEAyh/pJHks/Mlr -+rdPNEpotBjfV4M4BkgGAA/ipcmaAjcCIQCHvhwwKVBLzzTscT2HeUdEeBMoiXXK -JACAr3sJQJGxIQIgarRp+m1WSKV1MciwMaTOnbU7wxFs9DP1pva76lYBzgUCIQC9 -n0CnZCJ6IZYqSt0H5N7+Q+2Ro64nuwV/OSQfM6sBwQ== ------END RSA PRIVATE KEY-----''' - - # As above, but this is actually an unencrypted PKCS#8 key - rsaKeyPEM8 = u'''-----BEGIN PRIVATE KEY----- -MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAvx4nkAqgiyNRGlwS -ga5tkzEsPv6RP5MuvtSS8S0WtGEMMoy24girX0WsvilQgzKY8xIsGfeEkt7fQPDj -wZAzhQIDAQABAkAJRIMSnxFN7fZ+2rwjAbxaiOXmYB3XAWIg6tn9S/xv3rdYk4mK -5BxU3b2/FTn4zL0Y9ntEDeGsMEQCgdQM+sg5AiEA8g8vPh2mGIP2KYCSK9jfVFzk -B8cmJBEDteLFNyMSSiMCIQDKH+kkeSz8yWv6t080Smi0GN9XgzgGSAYAD+KlyZoC -NwIhAIe+HDApUEvPNOxxPYd5R0R4EyiJdcokAICvewlAkbEhAiBqtGn6bVZIpXUx -yLAxpM6dtTvDEWz0M/Wm9rvqVgHOBQIhAL2fQKdkInohlipK3Qfk3v5D7ZGjrie7 -BX85JB8zqwHB ------END PRIVATE KEY-----''' - - # The same RSA private key as in rsaKeyPEM, but now encrypted - rsaKeyEncryptedPEM = ( - - # PEM encryption - # With DES and passphrase 'test' - ('test', u'''-----BEGIN RSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: DES-CBC,AF8F9A40BD2FA2FC - -Ckl9ex1kaVEWhYC2QBmfaF+YPiR4NFkRXA7nj3dcnuFEzBnY5XULupqQpQI3qbfA -u8GYS7+b3toWWiHZivHbAAUBPDIZG9hKDyB9Sq2VMARGsX1yW1zhNvZLIiVJzUHs -C6NxQ1IJWOXzTew/xM2I26kPwHIvadq+/VaT8gLQdjdH0jOiVNaevjWnLgrn1mLP -BCNRMdcexozWtAFNNqSzfW58MJL2OdMi21ED184EFytIc1BlB+FZiGZduwKGuaKy -9bMbdb/1PSvsSzPsqW7KSSrTw6MgJAFJg6lzIYvR5F4poTVBxwBX3+EyEmShiaNY -IRX3TgQI0IjrVuLmvlZKbGWP18FXj7I7k9tSsNOOzllTTdq3ny5vgM3A+ynfAaxp -dysKznQ6P+IoqML1WxAID4aGRMWka+uArOJ148Rbj9s= ------END RSA PRIVATE KEY-----'''), - - # PKCS8 encryption - ('winter', u'''-----BEGIN ENCRYPTED PRIVATE KEY----- -MIIBpjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIeZIsbW3O+JcCAggA -MBQGCCqGSIb3DQMHBAgSM2p0D8FilgSCAWBhFyP2tiGKVpGj3mO8qIBzinU60ApR -3unvP+N6j7LVgnV2lFGaXbJ6a1PbQXe+2D6DUyBLo8EMXrKKVLqOMGkFMHc0UaV6 -R6MmrsRDrbOqdpTuVRW+NVd5J9kQQh4xnfU/QrcPPt7vpJvSf4GzG0n666Ki50OV -M/feuVlIiyGXY6UWdVDpcOV72cq02eNUs/1JWdh2uEBvA9fCL0c07RnMrdT+CbJQ -NjJ7f8ULtp7xvR9O3Al/yJ4Wv3i4VxF1f3MCXzhlUD4I0ONlr0kJWgeQ80q/cWhw -ntvgJwnCn2XR1h6LA8Wp+0ghDTsL2NhJpWd78zClGhyU4r3hqu1XDjoXa7YCXCix -jCV15+ViDJzlNCwg+W6lRg18sSLkCT7alviIE0U5tHc6UPbbHwT5QqAxAABaP+nZ -CGqJGyiwBzrKebjgSm/KRd4C91XqcsysyH2kKPfT51MLAoD4xelOURBP ------END ENCRYPTED PRIVATE KEY-----''' - ), - ) - - rsaPublicKeyPEM = u'''-----BEGIN PUBLIC KEY----- -MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL8eJ5AKoIsjURpcEoGubZMxLD7+kT+T -Lr7UkvEtFrRhDDKMtuIIq19FrL4pUIMymPMSLBn3hJLe30Dw48GQM4UCAwEAAQ== ------END PUBLIC KEY-----''' - - # Obtained using 'ssh-keygen -i -m PKCS8 -f rsaPublicKeyPEM' - rsaPublicKeyOpenSSH = b('''ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQC/HieQCqCLI1EaXBKBrm2TMSw+/pE/ky6+1JLxLRa0YQwyjLbiCKtfRay+KVCDMpjzEiwZ94SS3t9A8OPBkDOF comment\n''') - - # The private key, in PKCS#1 format encoded with DER - rsaKeyDER = a2b_hex( - '''3082013b020100024100bf1e27900aa08b23511a5c1281ae6d93312c3efe - 913f932ebed492f12d16b4610c328cb6e208ab5f45acbe2950833298f312 - 2c19f78492dedf40f0e3c190338502030100010240094483129f114dedf6 - 7edabc2301bc5a88e5e6601dd7016220ead9fd4bfc6fdeb75893898ae41c - 54ddbdbf1539f8ccbd18f67b440de1ac30440281d40cfac839022100f20f - 2f3e1da61883f62980922bd8df545ce407c726241103b5e2c53723124a23 - 022100ca1fe924792cfcc96bfab74f344a68b418df578338064806000fe2 - a5c99a023702210087be1c3029504bcf34ec713d877947447813288975ca - 240080af7b094091b12102206ab469fa6d5648a57531c8b031a4ce9db53b - c3116cf433f5a6f6bbea5601ce05022100bd9f40a764227a21962a4add07 - e4defe43ed91a3ae27bb057f39241f33ab01c1 - '''.replace(" ","")) - - # The private key, in unencrypted PKCS#8 format encoded with DER - rsaKeyDER8 = a2b_hex( - '''30820155020100300d06092a864886f70d01010105000482013f3082013 - b020100024100bf1e27900aa08b23511a5c1281ae6d93312c3efe913f932 - ebed492f12d16b4610c328cb6e208ab5f45acbe2950833298f3122c19f78 - 492dedf40f0e3c190338502030100010240094483129f114dedf67edabc2 - 301bc5a88e5e6601dd7016220ead9fd4bfc6fdeb75893898ae41c54ddbdb - f1539f8ccbd18f67b440de1ac30440281d40cfac839022100f20f2f3e1da - 61883f62980922bd8df545ce407c726241103b5e2c53723124a23022100c - a1fe924792cfcc96bfab74f344a68b418df578338064806000fe2a5c99a0 - 23702210087be1c3029504bcf34ec713d877947447813288975ca240080a - f7b094091b12102206ab469fa6d5648a57531c8b031a4ce9db53bc3116cf - 433f5a6f6bbea5601ce05022100bd9f40a764227a21962a4add07e4defe4 - 3ed91a3ae27bb057f39241f33ab01c1 - '''.replace(" ","")) - - rsaPublicKeyDER = a2b_hex( - '''305c300d06092a864886f70d0101010500034b003048024100bf1e27900a - a08b23511a5c1281ae6d93312c3efe913f932ebed492f12d16b4610c328c - b6e208ab5f45acbe2950833298f3122c19f78492dedf40f0e3c190338502 - 03010001 - '''.replace(" ","")) - - n = int('BF 1E 27 90 0A A0 8B 23 51 1A 5C 12 81 AE 6D 93 31 2C 3E FE 91 3F 93 2E BE D4 92 F1 2D 16 B4 61 0C 32 8C B6 E2 08 AB 5F 45 AC BE 29 50 83 32 98 F3 12 2C 19 F7 84 92 DE DF 40 F0 E3 C1 90 33 85'.replace(" ",""),16) - e = 65537 - d = int('09 44 83 12 9F 11 4D ED F6 7E DA BC 23 01 BC 5A 88 E5 E6 60 1D D7 01 62 20 EA D9 FD 4B FC 6F DE B7 58 93 89 8A E4 1C 54 DD BD BF 15 39 F8 CC BD 18 F6 7B 44 0D E1 AC 30 44 02 81 D4 0C FA C8 39'.replace(" ",""),16) - p = int('00 F2 0F 2F 3E 1D A6 18 83 F6 29 80 92 2B D8 DF 54 5C E4 07 C7 26 24 11 03 B5 E2 C5 37 23 12 4A 23'.replace(" ",""),16) - q = int('00 CA 1F E9 24 79 2C FC C9 6B FA B7 4F 34 4A 68 B4 18 DF 57 83 38 06 48 06 00 0F E2 A5 C9 9A 02 37'.replace(" ",""),16) - - # This is q^{-1} mod p). fastmath and slowmath use pInv (p^{-1} - # mod q) instead! - qInv = int('00 BD 9F 40 A7 64 22 7A 21 96 2A 4A DD 07 E4 DE FE 43 ED 91 A3 AE 27 BB 05 7F 39 24 1F 33 AB 01 C1'.replace(" ",""),16) - pInv = inverse(p,q) - - def testImportKey1(self): - """Verify import of RSAPrivateKey DER SEQUENCE""" - key = RSA.importKey(self.rsaKeyDER) - self.failUnless(key.has_private()) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - self.assertEqual(key.d, self.d) - self.assertEqual(key.p, self.p) - self.assertEqual(key.q, self.q) - - def testImportKey2(self): - """Verify import of SubjectPublicKeyInfo DER SEQUENCE""" - key = RSA.importKey(self.rsaPublicKeyDER) - self.failIf(key.has_private()) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - - def testImportKey3unicode(self): - """Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as unicode""" - key = RSA.importKey(self.rsaKeyPEM) - self.assertEqual(key.has_private(),True) # assert_ - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - self.assertEqual(key.d, self.d) - self.assertEqual(key.p, self.p) - self.assertEqual(key.q, self.q) - - def testImportKey3bytes(self): - """Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as byte string""" - key = RSA.importKey(b(self.rsaKeyPEM)) - self.assertEqual(key.has_private(),True) # assert_ - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - self.assertEqual(key.d, self.d) - self.assertEqual(key.p, self.p) - self.assertEqual(key.q, self.q) - - def testImportKey4unicode(self): - """Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as unicode""" - key = RSA.importKey(self.rsaPublicKeyPEM) - self.assertEqual(key.has_private(),False) # failIf - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - - def testImportKey4bytes(self): - """Verify import of SubjectPublicKeyInfo DER SEQUENCE, encoded with PEM as byte string""" - key = RSA.importKey(b(self.rsaPublicKeyPEM)) - self.assertEqual(key.has_private(),False) # failIf - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - - def testImportKey5(self): - """Verifies that the imported key is still a valid RSA pair""" - key = RSA.importKey(self.rsaKeyPEM) - idem = key._encrypt(key._decrypt(89)) - self.assertEqual(idem, 89) - - def testImportKey6(self): - """Verifies that the imported key is still a valid RSA pair""" - key = RSA.importKey(self.rsaKeyDER) - idem = key._encrypt(key._decrypt(65)) - self.assertEqual(idem, 65) - - def testImportKey7(self): - """Verify import of OpenSSH public key""" - key = RSA.importKey(self.rsaPublicKeyOpenSSH) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - - def testImportKey8(self): - """Verify import of encrypted PrivateKeyInfo DER SEQUENCE""" - for t in self.rsaKeyEncryptedPEM: - key = RSA.importKey(t[1], t[0]) - self.failUnless(key.has_private()) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - self.assertEqual(key.d, self.d) - self.assertEqual(key.p, self.p) - self.assertEqual(key.q, self.q) - - def testImportKey9(self): - """Verify import of unencrypted PrivateKeyInfo DER SEQUENCE""" - key = RSA.importKey(self.rsaKeyDER8) - self.failUnless(key.has_private()) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - self.assertEqual(key.d, self.d) - self.assertEqual(key.p, self.p) - self.assertEqual(key.q, self.q) - - def testImportKey10(self): - """Verify import of unencrypted PrivateKeyInfo DER SEQUENCE, encoded with PEM""" - key = RSA.importKey(self.rsaKeyPEM8) - self.failUnless(key.has_private()) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - self.assertEqual(key.d, self.d) - self.assertEqual(key.p, self.p) - self.assertEqual(key.q, self.q) - - def testImportKey11(self): - """Verify import of RSAPublicKey DER SEQUENCE""" - der = asn1.DerSequence([17, 3]).encode() - key = RSA.importKey(der) - self.assertEqual(key.n, 17) - self.assertEqual(key.e, 3) - - def testImportKey12(self): - """Verify import of RSAPublicKey DER SEQUENCE, encoded with PEM""" - der = asn1.DerSequence([17, 3]).encode() - pem = der2pem(der) - key = RSA.importKey(pem) - self.assertEqual(key.n, 17) - self.assertEqual(key.e, 3) - - def test_import_key_windows_cr_lf(self): - pem_cr_lf = "\r\n".join(self.rsaKeyPEM.splitlines()) - key = RSA.importKey(pem_cr_lf) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - self.assertEqual(key.d, self.d) - self.assertEqual(key.p, self.p) - self.assertEqual(key.q, self.q) - - def test_import_empty(self): - self.assertRaises(ValueError, RSA.import_key, b"") - - ### - def testExportKey1(self): - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - derKey = key.export_key("DER") - self.assertEqual(derKey, self.rsaKeyDER) - - def testExportKey2(self): - key = RSA.construct([self.n, self.e]) - derKey = key.export_key("DER") - self.assertEqual(derKey, self.rsaPublicKeyDER) - - def testExportKey3(self): - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - pemKey = key.export_key("PEM") - self.assertEqual(pemKey, b(self.rsaKeyPEM)) - - def testExportKey4(self): - key = RSA.construct([self.n, self.e]) - pemKey = key.export_key("PEM") - self.assertEqual(pemKey, b(self.rsaPublicKeyPEM)) - - def testExportKey5(self): - key = RSA.construct([self.n, self.e]) - openssh_1 = key.export_key("OpenSSH").split() - openssh_2 = self.rsaPublicKeyOpenSSH.split() - self.assertEqual(openssh_1[0], openssh_2[0]) - self.assertEqual(openssh_1[1], openssh_2[1]) - - def testExportKey7(self): - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - derKey = key.export_key("DER", pkcs=8) - self.assertEqual(derKey, self.rsaKeyDER8) - - def testExportKey8(self): - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - pemKey = key.export_key("PEM", pkcs=8) - self.assertEqual(pemKey, b(self.rsaKeyPEM8)) - - def testExportKey9(self): - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - self.assertRaises(ValueError, key.export_key, "invalid-format") - - def testExportKey10(self): - # Export and re-import the encrypted key. It must match. - # PEM envelope, PKCS#1, old PEM encryption - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - outkey = key.export_key('PEM', 'test') - self.failUnless(tostr(outkey).find('4,ENCRYPTED')!=-1) - self.failUnless(tostr(outkey).find('BEGIN RSA PRIVATE KEY')!=-1) - inkey = RSA.importKey(outkey, 'test') - self.assertEqual(key.n, inkey.n) - self.assertEqual(key.e, inkey.e) - self.assertEqual(key.d, inkey.d) - - def testExportKey11(self): - # Export and re-import the encrypted key. It must match. - # PEM envelope, PKCS#1, old PEM encryption - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - outkey = key.export_key('PEM', 'test', pkcs=1) - self.failUnless(tostr(outkey).find('4,ENCRYPTED')!=-1) - self.failUnless(tostr(outkey).find('BEGIN RSA PRIVATE KEY')!=-1) - inkey = RSA.importKey(outkey, 'test') - self.assertEqual(key.n, inkey.n) - self.assertEqual(key.e, inkey.e) - self.assertEqual(key.d, inkey.d) - - def testExportKey12(self): - # Export and re-import the encrypted key. It must match. - # PEM envelope, PKCS#8, old PEM encryption - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - outkey = key.export_key('PEM', 'test', pkcs=8) - self.failUnless(tostr(outkey).find('4,ENCRYPTED')!=-1) - self.failUnless(tostr(outkey).find('BEGIN PRIVATE KEY')!=-1) - inkey = RSA.importKey(outkey, 'test') - self.assertEqual(key.n, inkey.n) - self.assertEqual(key.e, inkey.e) - self.assertEqual(key.d, inkey.d) - - def testExportKey13(self): - # Export and re-import the encrypted key. It must match. - # PEM envelope, PKCS#8, PKCS#8 encryption - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - outkey = key.export_key('PEM', 'test', pkcs=8, - protection='PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC') - self.failUnless(tostr(outkey).find('4,ENCRYPTED')==-1) - self.failUnless(tostr(outkey).find('BEGIN ENCRYPTED PRIVATE KEY')!=-1) - inkey = RSA.importKey(outkey, 'test') - self.assertEqual(key.n, inkey.n) - self.assertEqual(key.e, inkey.e) - self.assertEqual(key.d, inkey.d) - - def testExportKey14(self): - # Export and re-import the encrypted key. It must match. - # DER envelope, PKCS#8, PKCS#8 encryption - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - outkey = key.export_key('DER', 'test', pkcs=8) - inkey = RSA.importKey(outkey, 'test') - self.assertEqual(key.n, inkey.n) - self.assertEqual(key.e, inkey.e) - self.assertEqual(key.d, inkey.d) - - def testExportKey15(self): - # Verify that that error an condition is detected when trying to - # use a password with DER encoding and PKCS#1. - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - self.assertRaises(ValueError, key.export_key, 'DER', 'test', 1) - - def test_import_key(self): - """Verify that import_key is an alias to importKey""" - key = RSA.import_key(self.rsaPublicKeyDER) - self.failIf(key.has_private()) - self.assertEqual(key.n, self.n) - self.assertEqual(key.e, self.e) - - def test_exportKey(self): - key = RSA.construct([self.n, self.e, self.d, self.p, self.q, self.pInv]) - self.assertEqual(key.export_key(), key.exportKey()) - - -class ImportKeyFromX509Cert(unittest.TestCase): - - def test_x509v1(self): - - # Sample V1 certificate with a 1024 bit RSA key - x509_v1_cert = """ ------BEGIN CERTIFICATE----- -MIICOjCCAaMCAQEwDQYJKoZIhvcNAQEEBQAwfjENMAsGA1UEChMEQWNtZTELMAkG -A1UECxMCUkQxHDAaBgkqhkiG9w0BCQEWDXNwYW1AYWNtZS5vcmcxEzARBgNVBAcT -Ck1ldHJvcG9saXMxETAPBgNVBAgTCE5ldyBZb3JrMQswCQYDVQQGEwJVUzENMAsG -A1UEAxMEdGVzdDAeFw0xNDA3MTExOTU3MjRaFw0xNzA0MDYxOTU3MjRaME0xCzAJ -BgNVBAYTAlVTMREwDwYDVQQIEwhOZXcgWW9yazENMAsGA1UEChMEQWNtZTELMAkG -A1UECxMCUkQxDzANBgNVBAMTBmxhdHZpYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw -gYkCgYEAyG+kytdRj3TFbRmHDYp3TXugVQ81chew0qeOxZWOz80IjtWpgdOaCvKW -NCuc8wUR9BWrEQW+39SaRMLiQfQtyFSQZijc3nsEBu/Lo4uWZ0W/FHDRVSvkJA/V -Ex5NL5ikI+wbUeCV5KajGNDalZ8F1pk32+CBs8h1xNx5DyxuEHUCAwEAATANBgkq -hkiG9w0BAQQFAAOBgQCVQF9Y//Q4Psy+umEM38pIlbZ2hxC5xNz/MbVPwuCkNcGn -KYNpQJP+JyVTsPpO8RLZsAQDzRueMI3S7fbbwTzAflN0z19wvblvu93xkaBytVok -9VBAH28olVhy9b1MMeg2WOt5sUEQaFNPnwwsyiY9+HsRpvpRnPSQF+kyYVsshQ== ------END CERTIFICATE----- - """.strip() - - # RSA public key as dumped by openssl - exponent = 65537 - modulus_str = """ -00:c8:6f:a4:ca:d7:51:8f:74:c5:6d:19:87:0d:8a: -77:4d:7b:a0:55:0f:35:72:17:b0:d2:a7:8e:c5:95: -8e:cf:cd:08:8e:d5:a9:81:d3:9a:0a:f2:96:34:2b: -9c:f3:05:11:f4:15:ab:11:05:be:df:d4:9a:44:c2: -e2:41:f4:2d:c8:54:90:66:28:dc:de:7b:04:06:ef: -cb:a3:8b:96:67:45:bf:14:70:d1:55:2b:e4:24:0f: -d5:13:1e:4d:2f:98:a4:23:ec:1b:51:e0:95:e4:a6: -a3:18:d0:da:95:9f:05:d6:99:37:db:e0:81:b3:c8: -75:c4:dc:79:0f:2c:6e:10:75 - """ - modulus = int(re.sub("[^0-9a-f]","", modulus_str), 16) - - key = RSA.importKey(x509_v1_cert) - self.assertEqual(key.e, exponent) - self.assertEqual(key.n, modulus) - self.failIf(key.has_private()) - - def test_x509v3(self): - - # Sample V3 certificate with a 1024 bit RSA key - x509_v3_cert = """ ------BEGIN CERTIFICATE----- -MIIEcjCCAlqgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEL -MAkGA1UECAwCTUQxEjAQBgNVBAcMCUJhbHRpbW9yZTEQMA4GA1UEAwwHVGVzdCBD -QTEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFtcGxlLmNvbTAeFw0xNDA3MTIwOTM1 -MTJaFw0xNzA0MDcwOTM1MTJaMEQxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJNRDES -MBAGA1UEBwwJQmFsdGltb3JlMRQwEgYDVQQDDAtUZXN0IFNlcnZlcjCBnzANBgkq -hkiG9w0BAQEFAAOBjQAwgYkCgYEA/S7GJV2OcFdyNMQ4K75KrYFtMEn3VnEFdPHa -jyS37XlMxSh0oS4GeTGVUCJInl5Cpsv8WQdh03FfeOdvzp5IZ46OcjeOPiWnmjgl -2G5j7e2bDH7RSchGV+OD6Fb1Agvuu2/9iy8fdf3rPQ/7eAddzKUrzwacVbnW+tg2 -QtSXKRcCAwEAAaOB1TCB0jAdBgNVHQ4EFgQU/WwCX7FfWMIPDFfJ+I8a2COG+l8w -HwYDVR0jBBgwFoAUa0hkif3RMaraiWtsOOZZlLu9wJwwCQYDVR0TBAIwADALBgNV -HQ8EBAMCBeAwSgYDVR0RBEMwQYILZXhhbXBsZS5jb22CD3d3dy5leGFtcGxlLmNv -bYIQbWFpbC5leGFtcGxlLmNvbYIPZnRwLmV4YW1wbGUuY29tMCwGCWCGSAGG+EIB -DQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQsF -AAOCAgEAvO6xfdsGbnoK4My3eJthodTAjMjPwFVY133LH04QLcCv54TxKhtUg1fi -PgdjVe1HpTytPBfXy2bSZbXAN0abZCtw1rYrnn7o1g2pN8iypVq3zVn0iMTzQzxs -zEPO3bpR/UhNSf90PmCsS5rqZpAAnXSaAy1ClwHWk/0eG2pYkhE1m1ABVMN2lsAW -e9WxGk6IFqaI9O37NYQwmEypMs4DC+ECJEvbPFiqi3n0gbXCZJJ6omDA5xJldaYK -Oa7KR3s/qjBsu9UAiWpLBuFoSTHIF2aeRKRFmUdmzwo43eVPep65pY6eQ4AdL2RF -rqEuINbGlzI5oQyYhu71IwB+iPZXaZZPlwjLgOsuad/p2hOgDb5WxUi8FnDPursQ -ujfpIpmrOP/zpvvQWnwePI3lI+5n41kTBSbefXEdv6rXpHk3QRzB90uPxnXPdxSC -16ASA8bQT5an/1AgoE3k9CrcD2K0EmgaX0YI0HUhkyzbkg34EhpWJ6vvRUbRiNRo -9cIbt/ya9Y9u0Ja8GLXv6dwX0l0IdJMkL8KifXUFAVCujp1FBrr/gdmwQn8itANy -+qbnWSxmOvtaY0zcaFAcONuHva0h51/WqXOMO1eb8PhR4HIIYU8p1oBwQp7dSni8 -THDi1F+GG5PsymMDj5cWK42f+QzjVw5PrVmFqqrrEoMlx8DWh5Y= ------END CERTIFICATE----- -""".strip() - - # RSA public key as dumped by openssl - exponent = 65537 - modulus_str = """ -00:fd:2e:c6:25:5d:8e:70:57:72:34:c4:38:2b:be: -4a:ad:81:6d:30:49:f7:56:71:05:74:f1:da:8f:24: -b7:ed:79:4c:c5:28:74:a1:2e:06:79:31:95:50:22: -48:9e:5e:42:a6:cb:fc:59:07:61:d3:71:5f:78:e7: -6f:ce:9e:48:67:8e:8e:72:37:8e:3e:25:a7:9a:38: -25:d8:6e:63:ed:ed:9b:0c:7e:d1:49:c8:46:57:e3: -83:e8:56:f5:02:0b:ee:bb:6f:fd:8b:2f:1f:75:fd: -eb:3d:0f:fb:78:07:5d:cc:a5:2b:cf:06:9c:55:b9: -d6:fa:d8:36:42:d4:97:29:17 - """ - modulus = int(re.sub("[^0-9a-f]","", modulus_str), 16) - - key = RSA.importKey(x509_v3_cert) - self.assertEqual(key.e, exponent) - self.assertEqual(key.n, modulus) - self.failIf(key.has_private()) - - -class TestImport_2048(unittest.TestCase): - - def test_import_openssh_public(self): - key_file_ref = load_file("rsa2048_private.pem") - key_file = load_file("rsa2048_public_openssh.txt") - - # Skip test if test vectors are not installed - if None in (key_file_ref, key_file): - return - - key_ref = RSA.import_key(key_file_ref).public_key() - key = RSA.import_key(key_file) - self.assertEqual(key_ref, key) - - def test_import_openssh_private_clear(self): - key_file = load_file("rsa2048_private_openssh.pem") - key_file_old = load_file("rsa2048_private_openssh_old.pem") - - # Skip test if test vectors are not installed - if None in (key_file_old, key_file): - return - - key = RSA.import_key(key_file) - key_old = RSA.import_key(key_file_old) - - self.assertEqual(key, key_old) - - def test_import_openssh_private_password(self): - key_file = load_file("rsa2048_private_openssh_pwd.pem") - key_file_old = load_file("rsa2048_private_openssh_pwd_old.pem") - - # Skip test if test vectors are not installed - if None in (key_file_old, key_file): - return - - key = RSA.import_key(key_file, b"password") - key_old = RSA.import_key(key_file_old) - self.assertEqual(key, key_old) - - -if __name__ == '__main__': - unittest.main() - - -def get_tests(config={}): - tests = [] - tests += list_test_cases(ImportKeyTests) - tests += list_test_cases(ImportKeyFromX509Cert) - tests += list_test_cases(TestImport_2048) - return tests - - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') - -# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/Crypto/SelfTest/Random/__init__.py b/Crypto/SelfTest/Random/__init__.py deleted file mode 100644 index 53061cc..0000000 --- a/Crypto/SelfTest/Random/__init__.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Random/__init__.py: Self-test for random number generation modules -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-test for random number generators""" - -__revision__ = "$Id$" - -def get_tests(config={}): - tests = [] - from Crypto.SelfTest.Random import test_random; tests += test_random.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: diff --git a/Crypto/SelfTest/Random/__pycache__/__init__.cpython-36.pyc b/Crypto/SelfTest/Random/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index 236df22..0000000 Binary files a/Crypto/SelfTest/Random/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Random/__pycache__/test_random.cpython-36.pyc b/Crypto/SelfTest/Random/__pycache__/test_random.cpython-36.pyc deleted file mode 100644 index 72f7210..0000000 Binary files a/Crypto/SelfTest/Random/__pycache__/test_random.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Random/test_random.py b/Crypto/SelfTest/Random/test_random.py deleted file mode 100644 index 8fadc53..0000000 --- a/Crypto/SelfTest/Random/test_random.py +++ /dev/null @@ -1,167 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Util/test_generic.py: Self-test for the Crypto.Random.new() function -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-test suite for Crypto.Random.new()""" - -import sys -import unittest -from Crypto.Util.py3compat import b - -class SimpleTest(unittest.TestCase): - def runTest(self): - """Crypto.Random.new()""" - # Import the Random module and try to use it - from Crypto import Random - randobj = Random.new() - x = randobj.read(16) - y = randobj.read(16) - self.assertNotEqual(x, y) - z = Random.get_random_bytes(16) - self.assertNotEqual(x, z) - self.assertNotEqual(y, z) - # Test the Random.random module, which - # implements a subset of Python's random API - # Not implemented: - # seed(), getstate(), setstate(), jumpahead() - # random(), uniform(), triangular(), betavariate() - # expovariate(), gammavariate(), gauss(), - # longnormvariate(), normalvariate(), - # vonmisesvariate(), paretovariate() - # weibullvariate() - # WichmannHill(), whseed(), SystemRandom() - from Crypto.Random import random - x = random.getrandbits(16*8) - y = random.getrandbits(16*8) - self.assertNotEqual(x, y) - # Test randrange - if x>y: - start = y - stop = x - else: - start = x - stop = y - for step in range(1,10): - x = random.randrange(start,stop,step) - y = random.randrange(start,stop,step) - self.assertNotEqual(x, y) - self.assertEqual(start <= x < stop, True) - self.assertEqual(start <= y < stop, True) - self.assertEqual((x - start) % step, 0) - self.assertEqual((y - start) % step, 0) - for i in range(10): - self.assertEqual(random.randrange(1,2), 1) - self.assertRaises(ValueError, random.randrange, start, start) - self.assertRaises(ValueError, random.randrange, stop, start, step) - self.assertRaises(TypeError, random.randrange, start, stop, step, step) - self.assertRaises(TypeError, random.randrange, start, stop, "1") - self.assertRaises(TypeError, random.randrange, "1", stop, step) - self.assertRaises(TypeError, random.randrange, 1, "2", step) - self.assertRaises(ValueError, random.randrange, start, stop, 0) - # Test randint - x = random.randint(start,stop) - y = random.randint(start,stop) - self.assertNotEqual(x, y) - self.assertEqual(start <= x <= stop, True) - self.assertEqual(start <= y <= stop, True) - for i in range(10): - self.assertEqual(random.randint(1,1), 1) - self.assertRaises(ValueError, random.randint, stop, start) - self.assertRaises(TypeError, random.randint, start, stop, step) - self.assertRaises(TypeError, random.randint, "1", stop) - self.assertRaises(TypeError, random.randint, 1, "2") - # Test choice - seq = range(10000) - x = random.choice(seq) - y = random.choice(seq) - self.assertNotEqual(x, y) - self.assertEqual(x in seq, True) - self.assertEqual(y in seq, True) - for i in range(10): - self.assertEqual(random.choice((1,2,3)) in (1,2,3), True) - self.assertEqual(random.choice([1,2,3]) in [1,2,3], True) - if sys.version_info[0] == 3: - self.assertEqual(random.choice(bytearray(b('123'))) in bytearray(b('123')), True) - self.assertEqual(1, random.choice([1])) - self.assertRaises(IndexError, random.choice, []) - self.assertRaises(TypeError, random.choice, 1) - # Test shuffle. Lacks random parameter to specify function. - # Make copies of seq - seq = range(500) - x = list(seq) - y = list(seq) - random.shuffle(x) - random.shuffle(y) - self.assertNotEqual(x, y) - self.assertEqual(len(seq), len(x)) - self.assertEqual(len(seq), len(y)) - for i in range(len(seq)): - self.assertEqual(x[i] in seq, True) - self.assertEqual(y[i] in seq, True) - self.assertEqual(seq[i] in x, True) - self.assertEqual(seq[i] in y, True) - z = [1] - random.shuffle(z) - self.assertEqual(z, [1]) - if sys.version_info[0] == 3: - z = bytearray(b('12')) - random.shuffle(z) - self.assertEqual(b('1') in z, True) - self.assertRaises(TypeError, random.shuffle, b('12')) - self.assertRaises(TypeError, random.shuffle, 1) - self.assertRaises(TypeError, random.shuffle, "11") - self.assertRaises(TypeError, random.shuffle, (1,2)) - # 2to3 wraps a list() around it, alas - but I want to shoot - # myself in the foot here! :D - # if sys.version_info[0] == 3: - # self.assertRaises(TypeError, random.shuffle, range(3)) - # Test sample - x = random.sample(seq, 20) - y = random.sample(seq, 20) - self.assertNotEqual(x, y) - for i in range(20): - self.assertEqual(x[i] in seq, True) - self.assertEqual(y[i] in seq, True) - z = random.sample([1], 1) - self.assertEqual(z, [1]) - z = random.sample((1,2,3), 1) - self.assertEqual(z[0] in (1,2,3), True) - z = random.sample("123", 1) - self.assertEqual(z[0] in "123", True) - z = random.sample(range(3), 1) - self.assertEqual(z[0] in range(3), True) - if sys.version_info[0] == 3: - z = random.sample(b("123"), 1) - self.assertEqual(z[0] in b("123"), True) - z = random.sample(bytearray(b("123")), 1) - self.assertEqual(z[0] in bytearray(b("123")), True) - self.assertRaises(TypeError, random.sample, 1) - -def get_tests(config={}): - return [SimpleTest()] - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') - -# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/Crypto/SelfTest/Signature/__init__.py b/Crypto/SelfTest/Signature/__init__.py deleted file mode 100644 index 88c7f34..0000000 --- a/Crypto/SelfTest/Signature/__init__.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Signature/__init__.py: Self-test for signature modules -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-test for signature modules""" - -import os - -def get_tests(config={}): - tests = [] - from . import test_pkcs1_15; tests += test_pkcs1_15.get_tests(config=config) - from . import test_pss; tests += test_pss.get_tests(config=config) - from . import test_dss; tests += test_dss.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: diff --git a/Crypto/SelfTest/Signature/__pycache__/__init__.cpython-36.pyc b/Crypto/SelfTest/Signature/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index 78283df..0000000 Binary files a/Crypto/SelfTest/Signature/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Signature/__pycache__/test_dss.cpython-36.pyc b/Crypto/SelfTest/Signature/__pycache__/test_dss.cpython-36.pyc deleted file mode 100644 index ddb2eb3..0000000 Binary files a/Crypto/SelfTest/Signature/__pycache__/test_dss.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Signature/__pycache__/test_pkcs1_15.cpython-36.pyc b/Crypto/SelfTest/Signature/__pycache__/test_pkcs1_15.cpython-36.pyc deleted file mode 100644 index 8adb145..0000000 Binary files a/Crypto/SelfTest/Signature/__pycache__/test_pkcs1_15.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Signature/__pycache__/test_pss.cpython-36.pyc b/Crypto/SelfTest/Signature/__pycache__/test_pss.cpython-36.pyc deleted file mode 100644 index fa1b2ea..0000000 Binary files a/Crypto/SelfTest/Signature/__pycache__/test_pss.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Signature/test_dss.py b/Crypto/SelfTest/Signature/test_dss.py deleted file mode 100644 index 1d23e09..0000000 --- a/Crypto/SelfTest/Signature/test_dss.py +++ /dev/null @@ -1,1132 +0,0 @@ -# -# SelfTest/Signature/test_dss.py: Self-test for DSS signatures -# -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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 re -import unittest -from binascii import hexlify, unhexlify - -from Crypto.Util.py3compat import tobytes, bord, bchr - -from Crypto.Hash import (SHA1, SHA224, SHA256, SHA384, SHA512, SHA3_256, - SHA3_384, SHA3_512) -from Crypto.Signature import DSS -from Crypto.PublicKey import DSA, ECC -from Crypto.SelfTest.st_common import list_test_cases -from Crypto.SelfTest.loader import load_test_vectors, load_test_vectors_wycheproof -from Crypto.Util.number import bytes_to_long, long_to_bytes - - -def t2b(hexstring): - ws = hexstring.replace(" ", "").replace("\n", "") - return unhexlify(tobytes(ws)) - - -def t2l(hexstring): - ws = hexstring.replace(" ", "").replace("\n", "") - return int(ws, 16) - - -def load_hash_by_name(hash_name): - return __import__("Crypto.Hash." + hash_name, globals(), locals(), ["new"]) - - -class StrRNG: - - def __init__(self, randomness): - length = len(randomness) - self._idx = 0 - # Fix required to get the right K (see how randint() works!) - self._randomness = long_to_bytes(bytes_to_long(randomness) - 1, length) - - def __call__(self, n): - out = self._randomness[self._idx:self._idx + n] - self._idx += n - return out - - -class FIPS_DSA_Tests(unittest.TestCase): - - # 1st 1024 bit key from SigGen.txt - P = 0xa8f9cd201e5e35d892f85f80e4db2599a5676a3b1d4f190330ed3256b26d0e80a0e49a8fffaaad2a24f472d2573241d4d6d6c7480c80b4c67bb4479c15ada7ea8424d2502fa01472e760241713dab025ae1b02e1703a1435f62ddf4ee4c1b664066eb22f2e3bf28bb70a2a76e4fd5ebe2d1229681b5b06439ac9c7e9d8bde283 - Q = 0xf85f0f83ac4df7ea0cdf8f469bfeeaea14156495 - G = 0x2b3152ff6c62f14622b8f48e59f8af46883b38e79b8c74deeae9df131f8b856e3ad6c8455dab87cc0da8ac973417ce4f7878557d6cdf40b35b4a0ca3eb310c6a95d68ce284ad4e25ea28591611ee08b8444bd64b25f3f7c572410ddfb39cc728b9c936f85f419129869929cdb909a6a3a99bbe089216368171bd0ba81de4fe33 - X = 0xc53eae6d45323164c7d07af5715703744a63fc3a - Y = 0x313fd9ebca91574e1c2eebe1517c57e0c21b0209872140c5328761bbb2450b33f1b18b409ce9ab7c4cd8fda3391e8e34868357c199e16a6b2eba06d6749def791d79e95d3a4d09b24c392ad89dbf100995ae19c01062056bb14bce005e8731efde175f95b975089bdcdaea562b32786d96f5a31aedf75364008ad4fffebb970b - - key_pub = DSA.construct((Y, G, P, Q)) - key_priv = DSA.construct((Y, G, P, Q, X)) - - def shortDescription(self): - return "FIPS DSA Tests" - - def test_loopback(self): - hashed_msg = SHA512.new(b"test") - signer = DSS.new(self.key_priv, 'fips-186-3') - signature = signer.sign(hashed_msg) - - verifier = DSS.new(self.key_pub, 'fips-186-3') - verifier.verify(hashed_msg, signature) - - def test_negative_unapproved_hashes(self): - """Verify that unapproved hashes are rejected""" - - from Crypto.Hash import RIPEMD160 - - self.description = "Unapproved hash (RIPEMD160) test" - hash_obj = RIPEMD160.new() - signer = DSS.new(self.key_priv, 'fips-186-3') - self.assertRaises(ValueError, signer.sign, hash_obj) - self.assertRaises(ValueError, signer.verify, hash_obj, b"\x00" * 40) - - def test_negative_unknown_modes_encodings(self): - """Verify that unknown modes/encodings are rejected""" - - self.description = "Unknown mode test" - self.assertRaises(ValueError, DSS.new, self.key_priv, 'fips-186-0') - - self.description = "Unknown encoding test" - self.assertRaises(ValueError, DSS.new, self.key_priv, 'fips-186-3', 'xml') - - def test_asn1_encoding(self): - """Verify ASN.1 encoding""" - - self.description = "ASN.1 encoding test" - hash_obj = SHA1.new() - signer = DSS.new(self.key_priv, 'fips-186-3', 'der') - signature = signer.sign(hash_obj) - - # Verify that output looks like a DER SEQUENCE - self.assertEqual(bord(signature[0]), 48) - signer.verify(hash_obj, signature) - - # Verify that ASN.1 parsing fails as expected - signature = bchr(7) + signature[1:] - self.assertRaises(ValueError, signer.verify, hash_obj, signature) - - def test_sign_verify(self): - """Verify public/private method""" - - self.description = "can_sign() test" - signer = DSS.new(self.key_priv, 'fips-186-3') - self.failUnless(signer.can_sign()) - - signer = DSS.new(self.key_pub, 'fips-186-3') - self.failIf(signer.can_sign()) - - -class FIPS_DSA_Tests_KAT(unittest.TestCase): - pass - - -test_vectors_verify = load_test_vectors(("Signature", "DSA"), - "FIPS_186_3_SigVer.rsp", - "Signature Verification 186-3", - {'result': lambda x: x}) or [] - -for idx, tv in enumerate(test_vectors_verify): - - if isinstance(tv, str): - res = re.match(r"\[mod = L=([0-9]+), N=([0-9]+), ([a-zA-Z0-9-]+)\]", tv) - assert(res) - hash_name = res.group(3).replace("-", "") - hash_module = load_hash_by_name(hash_name) - continue - - if hasattr(tv, "p"): - modulus = tv.p - generator = tv.g - suborder = tv.q - continue - - hash_obj = hash_module.new(tv.msg) - - comps = [bytes_to_long(x) for x in (tv.y, generator, modulus, suborder)] - key = DSA.construct(comps, False) # type: ignore - verifier = DSS.new(key, 'fips-186-3') - - def positive_test(self, verifier=verifier, hash_obj=hash_obj, signature=tv.r+tv.s): - verifier.verify(hash_obj, signature) - - def negative_test(self, verifier=verifier, hash_obj=hash_obj, signature=tv.r+tv.s): - self.assertRaises(ValueError, verifier.verify, hash_obj, signature) - - if tv.result == 'p': - setattr(FIPS_DSA_Tests_KAT, "test_verify_positive_%d" % idx, positive_test) - else: - setattr(FIPS_DSA_Tests_KAT, "test_verify_negative_%d" % idx, negative_test) - - -test_vectors_sign = load_test_vectors(("Signature", "DSA"), - "FIPS_186_3_SigGen.txt", - "Signature Creation 186-3", - {}) or [] - -for idx, tv in enumerate(test_vectors_sign): - - if isinstance(tv, str): - res = re.match(r"\[mod = L=([0-9]+), N=([0-9]+), ([a-zA-Z0-9-]+)\]", tv) - assert(res) - hash_name = res.group(3).replace("-", "") - hash_module = load_hash_by_name(hash_name) - continue - - if hasattr(tv, "p"): - modulus = tv.p - generator = tv.g - suborder = tv.q - continue - - hash_obj = hash_module.new(tv.msg) - comps_dsa = [bytes_to_long(x) for x in (tv.y, generator, modulus, suborder, tv.x)] - key = DSA.construct(comps_dsa, False) # type: ignore - signer = DSS.new(key, 'fips-186-3', randfunc=StrRNG(tv.k)) - - def new_test(self, signer=signer, hash_obj=hash_obj, signature=tv.r+tv.s): - self.assertEqual(signer.sign(hash_obj), signature) - setattr(FIPS_DSA_Tests_KAT, "test_sign_%d" % idx, new_test) - - -class FIPS_ECDSA_Tests(unittest.TestCase): - - key_priv = ECC.generate(curve="P-256") - key_pub = key_priv.public_key() - - def shortDescription(self): - return "FIPS ECDSA Tests" - - def test_loopback(self): - hashed_msg = SHA512.new(b"test") - signer = DSS.new(self.key_priv, 'fips-186-3') - signature = signer.sign(hashed_msg) - - verifier = DSS.new(self.key_pub, 'fips-186-3') - verifier.verify(hashed_msg, signature) - - def test_negative_unapproved_hashes(self): - """Verify that unapproved hashes are rejected""" - - from Crypto.Hash import SHA1 - - self.description = "Unapproved hash (SHA-1) test" - hash_obj = SHA1.new() - signer = DSS.new(self.key_priv, 'fips-186-3') - self.assertRaises(ValueError, signer.sign, hash_obj) - self.assertRaises(ValueError, signer.verify, hash_obj, b"\x00" * 40) - - def test_sign_verify(self): - """Verify public/private method""" - - self.description = "can_sign() test" - signer = DSS.new(self.key_priv, 'fips-186-3') - self.failUnless(signer.can_sign()) - - signer = DSS.new(self.key_pub, 'fips-186-3') - self.failIf(signer.can_sign()) - - def test_negative_unknown_modes_encodings(self): - """Verify that unknown modes/encodings are rejected""" - - self.description = "Unknown mode test" - self.assertRaises(ValueError, DSS.new, self.key_priv, 'fips-186-0') - - self.description = "Unknown encoding test" - self.assertRaises(ValueError, DSS.new, self.key_priv, 'fips-186-3', 'xml') - - def test_asn1_encoding(self): - """Verify ASN.1 encoding""" - - self.description = "ASN.1 encoding test" - hash_obj = SHA256.new() - signer = DSS.new(self.key_priv, 'fips-186-3', 'der') - signature = signer.sign(hash_obj) - - # Verify that output looks like a DER SEQUENCE - self.assertEqual(bord(signature[0]), 48) - signer.verify(hash_obj, signature) - - # Verify that ASN.1 parsing fails as expected - signature = bchr(7) + signature[1:] - self.assertRaises(ValueError, signer.verify, hash_obj, signature) - - -class FIPS_ECDSA_Tests_KAT(unittest.TestCase): - pass - - -test_vectors_verify = load_test_vectors(("Signature", "ECDSA"), - "SigVer.rsp", - "ECDSA Signature Verification 186-3", - {'result': lambda x: x, - 'qx': lambda x: int(x, 16), - 'qy': lambda x: int(x, 16), - }) or [] - -for idx, tv in enumerate(test_vectors_verify): - - if isinstance(tv, str): - res = re.match(r"\[(P-[0-9]+),(SHA-[0-9]+)\]", tv) - assert res - curve_name = res.group(1) - hash_name = res.group(2).replace("-", "") - hash_module = load_hash_by_name(hash_name) - continue - - hash_obj = hash_module.new(tv.msg) - ecc_key = ECC.construct(curve=curve_name, point_x=tv.qx, point_y=tv.qy) - verifier = DSS.new(ecc_key, 'fips-186-3') - - def positive_test(self, verifier=verifier, hash_obj=hash_obj, signature=tv.r+tv.s): - verifier.verify(hash_obj, signature) - - def negative_test(self, verifier=verifier, hash_obj=hash_obj, signature=tv.r+tv.s): - self.assertRaises(ValueError, verifier.verify, hash_obj, signature) - - if tv.result.startswith('p'): - setattr(FIPS_ECDSA_Tests_KAT, "test_verify_positive_%d" % idx, positive_test) - else: - setattr(FIPS_ECDSA_Tests_KAT, "test_verify_negative_%d" % idx, negative_test) - - -test_vectors_sign = load_test_vectors(("Signature", "ECDSA"), - "SigGen.txt", - "ECDSA Signature Verification 186-3", - {'d': lambda x: int(x, 16)}) or [] - -for idx, tv in enumerate(test_vectors_sign): - - if isinstance(tv, str): - res = re.match(r"\[(P-[0-9]+),(SHA-[0-9]+)\]", tv) - assert res - curve_name = res.group(1) - hash_name = res.group(2).replace("-", "") - hash_module = load_hash_by_name(hash_name) - continue - - hash_obj = hash_module.new(tv.msg) - ecc_key = ECC.construct(curve=curve_name, d=tv.d) - signer = DSS.new(ecc_key, 'fips-186-3', randfunc=StrRNG(tv.k)) - - def sign_test(self, signer=signer, hash_obj=hash_obj, signature=tv.r+tv.s): - self.assertEqual(signer.sign(hash_obj), signature) - setattr(FIPS_ECDSA_Tests_KAT, "test_sign_%d" % idx, sign_test) - - -class Det_DSA_Tests(unittest.TestCase): - """Tests from rfc6979""" - - # Each key is (p, q, g, x, y, desc) - keys = [ - ( - """ - 86F5CA03DCFEB225063FF830A0C769B9DD9D6153AD91D7CE27F787C43278B447 - E6533B86B18BED6E8A48B784A14C252C5BE0DBF60B86D6385BD2F12FB763ED88 - 73ABFD3F5BA2E0A8C0A59082EAC056935E529DAF7C610467899C77ADEDFC846C - 881870B7B19B2B58F9BE0521A17002E3BDD6B86685EE90B3D9A1B02B782B1779""", - "996F967F6C8E388D9E28D01E205FBA957A5698B1", - """ - 07B0F92546150B62514BB771E2A0C0CE387F03BDA6C56B505209FF25FD3C133D - 89BBCD97E904E09114D9A7DEFDEADFC9078EA544D2E401AEECC40BB9FBBF78FD - 87995A10A1C27CB7789B594BA7EFB5C4326A9FE59A070E136DB77175464ADCA4 - 17BE5DCE2F40D10A46A3A3943F26AB7FD9C0398FF8C76EE0A56826A8A88F1DBD""", - "411602CB19A6CCC34494D79D98EF1E7ED5AF25F7", - """ - 5DF5E01DED31D0297E274E1691C192FE5868FEF9E19A84776454B100CF16F653 - 92195A38B90523E2542EE61871C0440CB87C322FC4B4D2EC5E1E7EC766E1BE8D - 4CE935437DC11C3C8FD426338933EBFE739CB3465F4D3668C5E473508253B1E6 - 82F65CBDC4FAE93C2EA212390E54905A86E2223170B44EAA7DA5DD9FFCFB7F3B""", - "DSA1024" - ), - ( - """ - 9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48 - C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44F - FE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5 - B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51743BF33050C38DE2 - 35567E1B34C3D6A5C0CEAA1A0F368213C3D19843D0B4B09DCB9FC72D39C8DE41 - F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE - 92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA15 - 3E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B""", - "F2C3119374CE76C9356990B465374A17F23F9ED35089BD969F61C6DDE9998C1F", - """ - 5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613 - D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C4 - 6A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472 - 085057F3494309FFA73C611F78B32ADBB5740C361C9F35BE90997DB2014E2EF5 - AA61782F52ABEB8BD6432C4DD097BC5423B285DAFB60DC364E8161F4A2A35ACA - 3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71 - BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0 - DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7""", - "69C7548C21D0DFEA6B9A51C9EAD4E27C33D3B3F180316E5BCAB92C933F0E4DBC", - """ - 667098C654426C78D7F8201EAC6C203EF030D43605032C2F1FA937E5237DBD94 - 9F34A0A2564FE126DC8B715C5141802CE0979C8246463C40E6B6BDAA2513FA61 - 1728716C2E4FD53BC95B89E69949D96512E873B9C8F8DFD499CC312882561ADE - CB31F658E934C0C197F2C4D96B05CBAD67381E7B768891E4DA3843D24D94CDFB - 5126E9B8BF21E8358EE0E0A30EF13FD6A664C0DCE3731F7FB49A4845A4FD8254 - 687972A2D382599C9BAC4E0ED7998193078913032558134976410B89D2C171D1 - 23AC35FD977219597AA7D15C1A9A428E59194F75C721EBCBCFAE44696A499AFA - 74E04299F132026601638CB87AB79190D4A0986315DA8EEC6561C938996BEADF""", - "DSA2048" - ), - ] - - # This is a sequence of items: - # message, k, r, s, hash module - signatures = [ - ( - "sample", - "7BDB6B0FF756E1BB5D53583EF979082F9AD5BD5B", - "2E1A0C2562B2912CAAF89186FB0F42001585DA55", - "29EFB6B0AFF2D7A68EB70CA313022253B9A88DF5", - SHA1, - 'DSA1024' - ), - ( - "sample", - "562097C06782D60C3037BA7BE104774344687649", - "4BC3B686AEA70145856814A6F1BB53346F02101E", - "410697B92295D994D21EDD2F4ADA85566F6F94C1", - SHA224, - 'DSA1024' - ), - ( - "sample", - "519BA0546D0C39202A7D34D7DFA5E760B318BCFB", - "81F2F5850BE5BC123C43F71A3033E9384611C545", - "4CDD914B65EB6C66A8AAAD27299BEE6B035F5E89", - SHA256, - 'DSA1024' - ), - ( - "sample", - "95897CD7BBB944AA932DBC579C1C09EB6FCFC595", - "07F2108557EE0E3921BC1774F1CA9B410B4CE65A", - "54DF70456C86FAC10FAB47C1949AB83F2C6F7595", - SHA384, - 'DSA1024' - ), - ( - "sample", - "09ECE7CA27D0F5A4DD4E556C9DF1D21D28104F8B", - "16C3491F9B8C3FBBDD5E7A7B667057F0D8EE8E1B", - "02C36A127A7B89EDBB72E4FFBC71DABC7D4FC69C", - SHA512, - 'DSA1024' - ), - ( - "test", - "5C842DF4F9E344EE09F056838B42C7A17F4A6433", - "42AB2052FD43E123F0607F115052A67DCD9C5C77", - "183916B0230D45B9931491D4C6B0BD2FB4AAF088", - SHA1, - 'DSA1024' - ), - ( - "test", - "4598B8EFC1A53BC8AECD58D1ABBB0C0C71E67297", - "6868E9964E36C1689F6037F91F28D5F2C30610F2", - "49CEC3ACDC83018C5BD2674ECAAD35B8CD22940F", - SHA224, - 'DSA1024' - ), - ( - "test", - "5A67592E8128E03A417B0484410FB72C0B630E1A", - "22518C127299B0F6FDC9872B282B9E70D0790812", - "6837EC18F150D55DE95B5E29BE7AF5D01E4FE160", - SHA256, - 'DSA1024' - ), - ( - "test", - "220156B761F6CA5E6C9F1B9CF9C24BE25F98CD89", - "854CF929B58D73C3CBFDC421E8D5430CD6DB5E66", - "91D0E0F53E22F898D158380676A871A157CDA622", - SHA384, - 'DSA1024' - ), - ( - "test", - "65D2C2EEB175E370F28C75BFCDC028D22C7DBE9C", - "8EA47E475BA8AC6F2D821DA3BD212D11A3DEB9A0", - "7C670C7AD72B6C050C109E1790008097125433E8", - SHA512, - 'DSA1024' - ), - ( - "sample", - "888FA6F7738A41BDC9846466ABDB8174C0338250AE50CE955CA16230F9CBD53E", - "3A1B2DBD7489D6ED7E608FD036C83AF396E290DBD602408E8677DAABD6E7445A", - "D26FCBA19FA3E3058FFC02CA1596CDBB6E0D20CB37B06054F7E36DED0CDBBCCF", - SHA1, - 'DSA2048' - ), - ( - "sample", - "BC372967702082E1AA4FCE892209F71AE4AD25A6DFD869334E6F153BD0C4D806", - "DC9F4DEADA8D8FF588E98FED0AB690FFCE858DC8C79376450EB6B76C24537E2C", - "A65A9C3BC7BABE286B195D5DA68616DA8D47FA0097F36DD19F517327DC848CEC", - SHA224, - 'DSA2048' - ), - ( - "sample", - "8926A27C40484216F052F4427CFD5647338B7B3939BC6573AF4333569D597C52", - "EACE8BDBBE353C432A795D9EC556C6D021F7A03F42C36E9BC87E4AC7932CC809", - "7081E175455F9247B812B74583E9E94F9EA79BD640DC962533B0680793A38D53", - SHA256, - 'DSA2048' - ), - ( - "sample", - "C345D5AB3DA0A5BCB7EC8F8FB7A7E96069E03B206371EF7D83E39068EC564920", - "B2DA945E91858834FD9BF616EBAC151EDBC4B45D27D0DD4A7F6A22739F45C00B", - "19048B63D9FD6BCA1D9BAE3664E1BCB97F7276C306130969F63F38FA8319021B", - SHA384, - 'DSA2048' - ), - ( - "sample", - "5A12994431785485B3F5F067221517791B85A597B7A9436995C89ED0374668FC", - "2016ED092DC5FB669B8EFB3D1F31A91EECB199879BE0CF78F02BA062CB4C942E", - "D0C76F84B5F091E141572A639A4FB8C230807EEA7D55C8A154A224400AFF2351", - SHA512, - 'DSA2048' - ), - ( - "test", - "6EEA486F9D41A037B2C640BC5645694FF8FF4B98D066A25F76BE641CCB24BA4F", - "C18270A93CFC6063F57A4DFA86024F700D980E4CF4E2CB65A504397273D98EA0", - "414F22E5F31A8B6D33295C7539C1C1BA3A6160D7D68D50AC0D3A5BEAC2884FAA", - SHA1, - 'DSA2048' - ), - ( - "test", - "06BD4C05ED74719106223BE33F2D95DA6B3B541DAD7BFBD7AC508213B6DA6670", - "272ABA31572F6CC55E30BF616B7A265312018DD325BE031BE0CC82AA17870EA3", - "E9CC286A52CCE201586722D36D1E917EB96A4EBDB47932F9576AC645B3A60806", - SHA224, - 'DSA2048' - ), - ( - "test", - "1D6CE6DDA1C5D37307839CD03AB0A5CBB18E60D800937D67DFB4479AAC8DEAD7", - "8190012A1969F9957D56FCCAAD223186F423398D58EF5B3CEFD5A4146A4476F0", - "7452A53F7075D417B4B013B278D1BB8BBD21863F5E7B1CEE679CF2188E1AB19E", - SHA256, - 'DSA2048' - ), - ( - "test", - "206E61F73DBE1B2DC8BE736B22B079E9DACD974DB00EEBBC5B64CAD39CF9F91C", - "239E66DDBE8F8C230A3D071D601B6FFBDFB5901F94D444C6AF56F732BEB954BE", - "6BD737513D5E72FE85D1C750E0F73921FE299B945AAD1C802F15C26A43D34961", - SHA384, - 'DSA2048' - ), - ( - "test", - "AFF1651E4CD6036D57AA8B2A05CCF1A9D5A40166340ECBBDC55BE10B568AA0AA", - "89EC4BB1400ECCFF8E7D9AA515CD1DE7803F2DAFF09693EE7FD1353E90A68307", - "C9F0BDABCC0D880BB137A994CC7F3980CE91CC10FAF529FC46565B15CEA854E1", - SHA512, - 'DSA2048' - ) - ] - - def setUp(self): - # Convert DSA key components from hex strings to integers - # Each key is (p, q, g, x, y, desc) - - from collections import namedtuple - - TestKey = namedtuple('TestKey', 'p q g x y') - new_keys = {} - for k in self.keys: - tk = TestKey(*[t2l(y) for y in k[:-1]]) - new_keys[k[-1]] = tk - self.keys = new_keys - - # Convert signature encoding - TestSig = namedtuple('TestSig', 'message nonce result module test_key') - new_signatures = [] - for message, nonce, r, s, module, test_key in self.signatures: - tsig = TestSig( - tobytes(message), - t2l(nonce), - t2b(r) + t2b(s), - module, - self.keys[test_key] - ) - new_signatures.append(tsig) - self.signatures = new_signatures - - def test1(self): - q = 0x4000000000000000000020108A2E0CC0D99F8A5EF - x = 0x09A4D6792295A7F730FC3F2B49CBC0F62E862272F - p = 2 * q + 1 - y = pow(2, x, p) - key = DSA.construct([pow(y, 2, p), 2, p, q, x], False) - signer = DSS.new(key, 'deterministic-rfc6979') - - # Test _int2octets - self.assertEqual(hexlify(signer._int2octets(x)), - b'009a4d6792295a7f730fc3f2b49cbc0f62e862272f') - - # Test _bits2octets - h1 = SHA256.new(b"sample").digest() - self.assertEqual(hexlify(signer._bits2octets(h1)), - b'01795edf0d54db760f156d0dac04c0322b3a204224') - - def test2(self): - - for sig in self.signatures: - tk = sig.test_key - key = DSA.construct([tk.y, tk.g, tk.p, tk.q, tk.x], False) - signer = DSS.new(key, 'deterministic-rfc6979') - - hash_obj = sig.module.new(sig.message) - result = signer.sign(hash_obj) - self.assertEqual(sig.result, result) - - -class Det_ECDSA_Tests(unittest.TestCase): - - key_priv_p256 = ECC.construct(curve="P-256", d=0xC9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721) - key_pub_p256 = key_priv_p256.public_key() - - key_priv_p384 = ECC.construct(curve="P-384", d=0x6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5) - key_pub_p384 = key_priv_p384.public_key() - - key_priv_p521 = ECC.construct(curve="P-521", d=0x0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538) - key_pub_p521 = key_priv_p521.public_key() - - # This is a sequence of items: - # message, k, r, s, hash module - # taken from RFC6979 - signatures_p256_ = ( - ( - "sample", - "882905F1227FD620FBF2ABF21244F0BA83D0DC3A9103DBBEE43A1FB858109DB4", - "61340C88C3AAEBEB4F6D667F672CA9759A6CCAA9FA8811313039EE4A35471D32", - "6D7F147DAC089441BB2E2FE8F7A3FA264B9C475098FDCF6E00D7C996E1B8B7EB", - SHA1 - ), - ( - "sample", - "103F90EE9DC52E5E7FB5132B7033C63066D194321491862059967C715985D473", - "53B2FFF5D1752B2C689DF257C04C40A587FABABB3F6FC2702F1343AF7CA9AA3F", - "B9AFB64FDC03DC1A131C7D2386D11E349F070AA432A4ACC918BEA988BF75C74C", - SHA224 - ), - ( - "sample", - "A6E3C57DD01ABE90086538398355DD4C3B17AA873382B0F24D6129493D8AAD60", - "EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716", - "F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8", - SHA256 - ), - ( - "sample", - "09F634B188CEFD98E7EC88B1AA9852D734D0BC272F7D2A47DECC6EBEB375AAD4", - "0EAFEA039B20E9B42309FB1D89E213057CBF973DC0CFC8F129EDDDC800EF7719", - "4861F0491E6998B9455193E34E7B0D284DDD7149A74B95B9261F13ABDE940954", - SHA384 - ), - ( - "sample", - "5FA81C63109BADB88C1F367B47DA606DA28CAD69AA22C4FE6AD7DF73A7173AA5", - "8496A60B5E9B47C825488827E0495B0E3FA109EC4568FD3F8D1097678EB97F00", - "2362AB1ADBE2B8ADF9CB9EDAB740EA6049C028114F2460F96554F61FAE3302FE", - SHA512 - ), - ( - "test", - "8C9520267C55D6B980DF741E56B4ADEE114D84FBFA2E62137954164028632A2E", - "0CBCC86FD6ABD1D99E703E1EC50069EE5C0B4BA4B9AC60E409E8EC5910D81A89", - "01B9D7B73DFAA60D5651EC4591A0136F87653E0FD780C3B1BC872FFDEAE479B1", - SHA1 - ), - ( - "test", - "669F4426F2688B8BE0DB3A6BD1989BDAEFFF84B649EEB84F3DD26080F667FAA7", - "C37EDB6F0AE79D47C3C27E962FA269BB4F441770357E114EE511F662EC34A692", - "C820053A05791E521FCAAD6042D40AEA1D6B1A540138558F47D0719800E18F2D", - SHA224 - ), - ( - "test", - "D16B6AE827F17175E040871A1C7EC3500192C4C92677336EC2537ACAEE0008E0", - "F1ABB023518351CD71D881567B1EA663ED3EFCF6C5132B354F28D3B0B7D38367", - "019F4113742A2B14BD25926B49C649155F267E60D3814B4C0CC84250E46F0083", - SHA256 - ), - ( - "test", - "16AEFFA357260B04B1DD199693960740066C1A8F3E8EDD79070AA914D361B3B8", - "83910E8B48BB0C74244EBDF7F07A1C5413D61472BD941EF3920E623FBCCEBEB6", - "8DDBEC54CF8CD5874883841D712142A56A8D0F218F5003CB0296B6B509619F2C", - SHA384 - ), - ( - "test", - "6915D11632ACA3C40D5D51C08DAF9C555933819548784480E93499000D9F0B7F", - "461D93F31B6540894788FD206C07CFA0CC35F46FA3C91816FFF1040AD1581A04", - "39AF9F15DE0DB8D97E72719C74820D304CE5226E32DEDAE67519E840D1194E55", - SHA512 - ) - ) - - signatures_p384_ = ( - ( - "sample", - "4471EF7518BB2C7C20F62EAE1C387AD0C5E8E470995DB4ACF694466E6AB096630F29E5938D25106C3C340045A2DB01A7", - "EC748D839243D6FBEF4FC5C4859A7DFFD7F3ABDDF72014540C16D73309834FA37B9BA002899F6FDA3A4A9386790D4EB2", - "A3BCFA947BEEF4732BF247AC17F71676CB31A847B9FF0CBC9C9ED4C1A5B3FACF26F49CA031D4857570CCB5CA4424A443", - SHA1 - ), - ( - "sample", - "A4E4D2F0E729EB786B31FC20AD5D849E304450E0AE8E3E341134A5C1AFA03CAB8083EE4E3C45B06A5899EA56C51B5879", - "42356E76B55A6D9B4631C865445DBE54E056D3B3431766D0509244793C3F9366450F76EE3DE43F5A125333A6BE060122", - "9DA0C81787064021E78DF658F2FBB0B042BF304665DB721F077A4298B095E4834C082C03D83028EFBF93A3C23940CA8D", - SHA224 - ), - ( - "sample", - "180AE9F9AEC5438A44BC159A1FCB277C7BE54FA20E7CF404B490650A8ACC414E375572342863C899F9F2EDF9747A9B60", - "21B13D1E013C7FA1392D03C5F99AF8B30C570C6F98D4EA8E354B63A21D3DAA33BDE1E888E63355D92FA2B3C36D8FB2CD", - "F3AA443FB107745BF4BD77CB3891674632068A10CA67E3D45DB2266FA7D1FEEBEFDC63ECCD1AC42EC0CB8668A4FA0AB0", - SHA256 - ), - ( - "sample", - "94ED910D1A099DAD3254E9242AE85ABDE4BA15168EAF0CA87A555FD56D10FBCA2907E3E83BA95368623B8C4686915CF9", - "94EDBB92A5ECB8AAD4736E56C691916B3F88140666CE9FA73D64C4EA95AD133C81A648152E44ACF96E36DD1E80FABE46", - "99EF4AEB15F178CEA1FE40DB2603138F130E740A19624526203B6351D0A3A94FA329C145786E679E7B82C71A38628AC8", - SHA384 - ), - ( - "sample", - "92FC3C7183A883E24216D1141F1A8976C5B0DD797DFA597E3D7B32198BD35331A4E966532593A52980D0E3AAA5E10EC3", - "ED0959D5880AB2D869AE7F6C2915C6D60F96507F9CB3E047C0046861DA4A799CFE30F35CC900056D7C99CD7882433709", - "512C8CCEEE3890A84058CE1E22DBC2198F42323CE8ACA9135329F03C068E5112DC7CC3EF3446DEFCEB01A45C2667FDD5", - SHA512 - ), - ( - "test", - "66CC2C8F4D303FC962E5FF6A27BD79F84EC812DDAE58CF5243B64A4AD8094D47EC3727F3A3C186C15054492E30698497", - "4BC35D3A50EF4E30576F58CD96CE6BF638025EE624004A1F7789A8B8E43D0678ACD9D29876DAF46638645F7F404B11C7", - "D5A6326C494ED3FF614703878961C0FDE7B2C278F9A65FD8C4B7186201A2991695BA1C84541327E966FA7B50F7382282", - SHA1 - ), - ( - "test", - "18FA39DB95AA5F561F30FA3591DC59C0FA3653A80DAFFA0B48D1A4C6DFCBFF6E3D33BE4DC5EB8886A8ECD093F2935726", - "E8C9D0B6EA72A0E7837FEA1D14A1A9557F29FAA45D3E7EE888FC5BF954B5E62464A9A817C47FF78B8C11066B24080E72", - "07041D4A7A0379AC7232FF72E6F77B6DDB8F09B16CCE0EC3286B2BD43FA8C6141C53EA5ABEF0D8231077A04540A96B66", - SHA224 - ), - ( - "test", - "0CFAC37587532347DC3389FDC98286BBA8C73807285B184C83E62E26C401C0FAA48DD070BA79921A3457ABFF2D630AD7", - "6D6DEFAC9AB64DABAFE36C6BF510352A4CC27001263638E5B16D9BB51D451559F918EEDAF2293BE5B475CC8F0188636B", - "2D46F3BECBCC523D5F1A1256BF0C9B024D879BA9E838144C8BA6BAEB4B53B47D51AB373F9845C0514EEFB14024787265", - SHA256 - ), - ( - "test", - "015EE46A5BF88773ED9123A5AB0807962D193719503C527B031B4C2D225092ADA71F4A459BC0DA98ADB95837DB8312EA", - "8203B63D3C853E8D77227FB377BCF7B7B772E97892A80F36AB775D509D7A5FEB0542A7F0812998DA8F1DD3CA3CF023DB", - "DDD0760448D42D8A43AF45AF836FCE4DE8BE06B485E9B61B827C2F13173923E06A739F040649A667BF3B828246BAA5A5", - SHA384 - ), - ( - "test", - "3780C4F67CB15518B6ACAE34C9F83568D2E12E47DEAB6C50A4E4EE5319D1E8CE0E2CC8A136036DC4B9C00E6888F66B6C", - "A0D5D090C9980FAF3C2CE57B7AE951D31977DD11C775D314AF55F76C676447D06FB6495CD21B4B6E340FC236584FB277", - "976984E59B4C77B0E8E4460DCA3D9F20E07B9BB1F63BEEFAF576F6B2E8B224634A2092CD3792E0159AD9CEE37659C736", - SHA512 - ), - ) - - signatures_p521_ = ( - ( - "sample", - "0089C071B419E1C2820962321787258469511958E80582E95D8378E0C2CCDB3CB42BEDE42F50E3FA3C71F5A76724281D31D9C89F0F91FC1BE4918DB1C03A5838D0F9", - "00343B6EC45728975EA5CBA6659BBB6062A5FF89EEA58BE3C80B619F322C87910FE092F7D45BB0F8EEE01ED3F20BABEC079D202AE677B243AB40B5431D497C55D75D", - "00E7B0E675A9B24413D448B8CC119D2BF7B2D2DF032741C096634D6D65D0DBE3D5694625FB9E8104D3B842C1B0E2D0B98BEA19341E8676AEF66AE4EBA3D5475D5D16", - SHA1 - ), - ( - "sample", - "0121415EC2CD7726330A61F7F3FA5DE14BE9436019C4DB8CB4041F3B54CF31BE0493EE3F427FB906393D895A19C9523F3A1D54BB8702BD4AA9C99DAB2597B92113F3", - "01776331CFCDF927D666E032E00CF776187BC9FDD8E69D0DABB4109FFE1B5E2A30715F4CC923A4A5E94D2503E9ACFED92857B7F31D7152E0F8C00C15FF3D87E2ED2E", - "0050CB5265417FE2320BBB5A122B8E1A32BD699089851128E360E620A30C7E17BA41A666AF126CE100E5799B153B60528D5300D08489CA9178FB610A2006C254B41F", - SHA224 - ), - ( - "sample", - "00EDF38AFCAAECAB4383358B34D67C9F2216C8382AAEA44A3DAD5FDC9C32575761793FEF24EB0FC276DFC4F6E3EC476752F043CF01415387470BCBD8678ED2C7E1A0", - "01511BB4D675114FE266FC4372B87682BAECC01D3CC62CF2303C92B3526012659D16876E25C7C1E57648F23B73564D67F61C6F14D527D54972810421E7D87589E1A7", - "004A171143A83163D6DF460AAF61522695F207A58B95C0644D87E52AA1A347916E4F7A72930B1BC06DBE22CE3F58264AFD23704CBB63B29B931F7DE6C9D949A7ECFC", - SHA256 - ), - ( - "sample", - "01546A108BC23A15D6F21872F7DED661FA8431DDBD922D0DCDB77CC878C8553FFAD064C95A920A750AC9137E527390D2D92F153E66196966EA554D9ADFCB109C4211", - "01EA842A0E17D2DE4F92C15315C63DDF72685C18195C2BB95E572B9C5136CA4B4B576AD712A52BE9730627D16054BA40CC0B8D3FF035B12AE75168397F5D50C67451", - "01F21A3CEE066E1961025FB048BD5FE2B7924D0CD797BABE0A83B66F1E35EEAF5FDE143FA85DC394A7DEE766523393784484BDF3E00114A1C857CDE1AA203DB65D61", - SHA384 - ), - ( - "sample", - "01DAE2EA071F8110DC26882D4D5EAE0621A3256FC8847FB9022E2B7D28E6F10198B1574FDD03A9053C08A1854A168AA5A57470EC97DD5CE090124EF52A2F7ECBFFD3", - "00C328FAFCBD79DD77850370C46325D987CB525569FB63C5D3BC53950E6D4C5F174E25A1EE9017B5D450606ADD152B534931D7D4E8455CC91F9B15BF05EC36E377FA", - "00617CCE7CF5064806C467F678D3B4080D6F1CC50AF26CA209417308281B68AF282623EAA63E5B5C0723D8B8C37FF0777B1A20F8CCB1DCCC43997F1EE0E44DA4A67A", - SHA512 - ), - ( - "test", - "00BB9F2BF4FE1038CCF4DABD7139A56F6FD8BB1386561BD3C6A4FC818B20DF5DDBA80795A947107A1AB9D12DAA615B1ADE4F7A9DC05E8E6311150F47F5C57CE8B222", - "013BAD9F29ABE20DE37EBEB823C252CA0F63361284015A3BF430A46AAA80B87B0693F0694BD88AFE4E661FC33B094CD3B7963BED5A727ED8BD6A3A202ABE009D0367", - "01E9BB81FF7944CA409AD138DBBEE228E1AFCC0C890FC78EC8604639CB0DBDC90F717A99EAD9D272855D00162EE9527567DD6A92CBD629805C0445282BBC916797FF", - SHA1 - ), - ( - "test", - "0040D09FCF3C8A5F62CF4FB223CBBB2B9937F6B0577C27020A99602C25A01136987E452988781484EDBBCF1C47E554E7FC901BC3085E5206D9F619CFF07E73D6F706", - "01C7ED902E123E6815546065A2C4AF977B22AA8EADDB68B2C1110E7EA44D42086BFE4A34B67DDC0E17E96536E358219B23A706C6A6E16BA77B65E1C595D43CAE17FB", - "0177336676304FCB343CE028B38E7B4FBA76C1C1B277DA18CAD2A8478B2A9A9F5BEC0F3BA04F35DB3E4263569EC6AADE8C92746E4C82F8299AE1B8F1739F8FD519A4", - SHA224 - ), - ( - "test", - "001DE74955EFAABC4C4F17F8E84D881D1310B5392D7700275F82F145C61E843841AF09035BF7A6210F5A431A6A9E81C9323354A9E69135D44EBD2FCAA7731B909258", - "000E871C4A14F993C6C7369501900C4BC1E9C7B0B4BA44E04868B30B41D8071042EB28C4C250411D0CE08CD197E4188EA4876F279F90B3D8D74A3C76E6F1E4656AA8", - "00CD52DBAA33B063C3A6CD8058A1FB0A46A4754B034FCC644766CA14DA8CA5CA9FDE00E88C1AD60CCBA759025299079D7A427EC3CC5B619BFBC828E7769BCD694E86", - SHA256 - ), - ( - "test", - "01F1FC4A349A7DA9A9E116BFDD055DC08E78252FF8E23AC276AC88B1770AE0B5DCEB1ED14A4916B769A523CE1E90BA22846AF11DF8B300C38818F713DADD85DE0C88", - "014BEE21A18B6D8B3C93FAB08D43E739707953244FDBE924FA926D76669E7AC8C89DF62ED8975C2D8397A65A49DCC09F6B0AC62272741924D479354D74FF6075578C", - "0133330865C067A0EAF72362A65E2D7BC4E461E8C8995C3B6226A21BD1AA78F0ED94FE536A0DCA35534F0CD1510C41525D163FE9D74D134881E35141ED5E8E95B979", - SHA384 - ), - ( - "test", - "016200813020EC986863BEDFC1B121F605C1215645018AEA1A7B215A564DE9EB1B38A67AA1128B80CE391C4FB71187654AAA3431027BFC7F395766CA988C964DC56D", - "013E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47EE6D", - "01FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4DCE3", - SHA512 - ), - ) - - signatures_p256 = [] - for a, b, c, d, e in signatures_p256_: - new_tv = (tobytes(a), unhexlify(b), unhexlify(c), unhexlify(d), e) - signatures_p256.append(new_tv) - - signatures_p384 = [] - for a, b, c, d, e in signatures_p384_: - new_tv = (tobytes(a), unhexlify(b), unhexlify(c), unhexlify(d), e) - signatures_p384.append(new_tv) - - signatures_p521 = [] - for a, b, c, d, e in signatures_p521_: - new_tv = (tobytes(a), unhexlify(b), unhexlify(c), unhexlify(d), e) - signatures_p521.append(new_tv) - - def shortDescription(self): - return "Deterministic ECDSA Tests" - - def test_loopback_p256(self): - hashed_msg = SHA512.new(b"test") - signer = DSS.new(self.key_priv_p256, 'deterministic-rfc6979') - signature = signer.sign(hashed_msg) - - verifier = DSS.new(self.key_pub_p256, 'deterministic-rfc6979') - verifier.verify(hashed_msg, signature) - - def test_loopback_p384(self): - hashed_msg = SHA512.new(b"test") - signer = DSS.new(self.key_priv_p384, 'deterministic-rfc6979') - signature = signer.sign(hashed_msg) - - verifier = DSS.new(self.key_pub_p384, 'deterministic-rfc6979') - verifier.verify(hashed_msg, signature) - - def test_loopback_p521(self): - hashed_msg = SHA512.new(b"test") - signer = DSS.new(self.key_priv_p521, 'deterministic-rfc6979') - signature = signer.sign(hashed_msg) - - verifier = DSS.new(self.key_pub_p521, 'deterministic-rfc6979') - verifier.verify(hashed_msg, signature) - - def test_data_rfc6979_p256(self): - signer = DSS.new(self.key_priv_p256, 'deterministic-rfc6979') - for message, k, r, s, module in self.signatures_p256: - hash_obj = module.new(message) - result = signer.sign(hash_obj) - self.assertEqual(r + s, result) - - def test_data_rfc6979_p384(self): - signer = DSS.new(self.key_priv_p384, 'deterministic-rfc6979') - for message, k, r, s, module in self.signatures_p384: - hash_obj = module.new(message) - result = signer.sign(hash_obj) - self.assertEqual(r + s, result) - - def test_data_rfc6979_p521(self): - signer = DSS.new(self.key_priv_p521, 'deterministic-rfc6979') - for message, k, r, s, module in self.signatures_p521: - hash_obj = module.new(message) - result = signer.sign(hash_obj) - self.assertEqual(r + s, result) - - -def get_hash_module(hash_name): - if hash_name == "SHA-512": - hash_module = SHA512 - elif hash_name == "SHA-512/224": - hash_module = SHA512.new(truncate="224") - elif hash_name == "SHA-512/256": - hash_module = SHA512.new(truncate="256") - elif hash_name == "SHA-384": - hash_module = SHA384 - elif hash_name == "SHA-256": - hash_module = SHA256 - elif hash_name == "SHA-224": - hash_module = SHA224 - elif hash_name == "SHA-1": - hash_module = SHA1 - else: - raise ValueError("Unknown hash algorithm: " + hash_name) - return hash_module - - -class TestVectorsDSAWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings, slow_tests): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._slow_tests = slow_tests - self._id = "None" - self.tv = [] - - def setUp(self): - - def filter_dsa(group): - return DSA.import_key(group['keyPem']) - - def filter_sha(group): - return get_hash_module(group['sha']) - - def filter_type(group): - sig_type = group['type'] - if sig_type != 'DsaVerify': - raise ValueError("Unknown signature type " + sig_type) - return sig_type - - result = load_test_vectors_wycheproof(("Signature", "wycheproof"), - "dsa_test.json", - "Wycheproof DSA signature", - group_tag={'key': filter_dsa, - 'hash_module': filter_sha, - 'sig_type': filter_type}) - self.tv += result - - def shortDescription(self): - return self._id - - 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_verify(self, tv): - self._id = "Wycheproof DSA Test #" + str(tv.id) - - hashed_msg = tv.hash_module.new(tv.msg) - signer = DSS.new(tv.key, 'fips-186-3', encoding='der') - try: - signature = signer.verify(hashed_msg, tv.sig) - except ValueError as e: - if tv.warning: - return - assert not tv.valid - else: - assert tv.valid - self.warn(tv) - - def runTest(self): - for tv in self.tv: - self.test_verify(tv) - - -class TestVectorsECDSAWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings, slow_tests): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._slow_tests = slow_tests - self._id = "None" - - def add_tests(self, filename): - - def filter_ecc(group): - # These are the only curves we accept to skip - if group['key']['curve'] in ('secp224r1', 'secp224k1', 'secp256k1', - 'brainpoolP224r1', 'brainpoolP224t1', - 'brainpoolP256r1', 'brainpoolP256t1', - 'brainpoolP320r1', 'brainpoolP320t1', - 'brainpoolP384r1', 'brainpoolP384t1', - 'brainpoolP512r1', 'brainpoolP512t1', - ): - return None - return ECC.import_key(group['keyPem']) - - def filter_sha(group): - return get_hash_module(group['sha']) - - def filter_encoding(group): - encoding_name = group['type'] - if encoding_name == "EcdsaVerify": - return "der" - elif encoding_name == "EcdsaP1363Verify": - return "binary" - else: - raise ValueError("Unknown signature type " + encoding_name) - - result = load_test_vectors_wycheproof(("Signature", "wycheproof"), - filename, - "Wycheproof ECDSA signature (%s)" % filename, - group_tag={'key': filter_ecc, - 'hash_module': filter_sha, - 'encoding': filter_encoding, - }) - self.tv += result - - def setUp(self): - self.tv = [] - self.add_tests("ecdsa_secp224r1_sha224_p1363_test.json") - self.add_tests("ecdsa_secp224r1_sha224_test.json") - if self._slow_tests: - self.add_tests("ecdsa_secp224r1_sha256_p1363_test.json") - self.add_tests("ecdsa_secp224r1_sha256_test.json") - self.add_tests("ecdsa_secp224r1_sha3_224_test.json") - self.add_tests("ecdsa_secp224r1_sha3_256_test.json") - self.add_tests("ecdsa_secp224r1_sha3_512_test.json") - self.add_tests("ecdsa_secp224r1_sha512_p1363_test.json") - self.add_tests("ecdsa_secp224r1_sha512_test.json") - self.add_tests("ecdsa_secp256r1_sha256_p1363_test.json") - self.add_tests("ecdsa_secp256r1_sha256_test.json") - self.add_tests("ecdsa_secp256r1_sha3_256_test.json") - self.add_tests("ecdsa_secp256r1_sha3_512_test.json") - self.add_tests("ecdsa_secp256r1_sha512_p1363_test.json") - self.add_tests("ecdsa_secp256r1_sha512_test.json") - if self._slow_tests: - self.add_tests("ecdsa_secp384r1_sha3_384_test.json") - self.add_tests("ecdsa_secp384r1_sha3_512_test.json") - self.add_tests("ecdsa_secp384r1_sha384_p1363_test.json") - self.add_tests("ecdsa_secp384r1_sha384_test.json") - self.add_tests("ecdsa_secp384r1_sha512_p1363_test.json") - self.add_tests("ecdsa_secp384r1_sha512_test.json") - if self._slow_tests: - self.add_tests("ecdsa_secp521r1_sha3_512_test.json") - self.add_tests("ecdsa_secp521r1_sha512_p1363_test.json") - self.add_tests("ecdsa_secp521r1_sha512_test.json") - self.add_tests("ecdsa_test.json") - self.add_tests("ecdsa_webcrypto_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_verify(self, tv): - self._id = "Wycheproof ECDSA Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename) - - # Skip tests with unsupported curves - if tv.key is None: - return - - hashed_msg = tv.hash_module.new(tv.msg) - signer = DSS.new(tv.key, 'fips-186-3', encoding=tv.encoding) - try: - signature = signer.verify(hashed_msg, tv.sig) - except ValueError as e: - if tv.warning: - return - if tv.comment == "k*G has a large x-coordinate": - return - assert not tv.valid - else: - assert tv.valid - self.warn(tv) - - def runTest(self): - for tv in self.tv: - self.test_verify(tv) - - -def get_tests(config={}): - wycheproof_warnings = config.get('wycheproof_warnings') - - tests = [] - tests += list_test_cases(FIPS_DSA_Tests) - tests += list_test_cases(FIPS_ECDSA_Tests) - tests += list_test_cases(Det_DSA_Tests) - tests += list_test_cases(Det_ECDSA_Tests) - - slow_tests = not config.get('slow_tests') - if slow_tests: - tests += list_test_cases(FIPS_DSA_Tests_KAT) - tests += list_test_cases(FIPS_ECDSA_Tests_KAT) - - tests += [TestVectorsDSAWycheproof(wycheproof_warnings, slow_tests)] - tests += [TestVectorsECDSAWycheproof(wycheproof_warnings, slow_tests)] - - return tests - - -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/Signature/test_pkcs1_15.py b/Crypto/SelfTest/Signature/test_pkcs1_15.py deleted file mode 100644 index 8e2c6ee..0000000 --- a/Crypto/SelfTest/Signature/test_pkcs1_15.py +++ /dev/null @@ -1,348 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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.Util.py3compat import bchr -from Crypto.Util.number import bytes_to_long -from Crypto.Util.strxor import strxor -from Crypto.SelfTest.st_common import list_test_cases -from Crypto.SelfTest.loader import load_test_vectors, load_test_vectors_wycheproof - -from Crypto.Hash import (SHA1, SHA224, SHA256, SHA384, SHA512, SHA3_384, - SHA3_224, SHA3_256, SHA3_512) -from Crypto.PublicKey import RSA -from Crypto.Signature import pkcs1_15 -from Crypto.Signature import PKCS1_v1_5 - -from Crypto.Util._file_system import pycryptodome_filename -from Crypto.Util.strxor import strxor - - -def load_hash_by_name(hash_name): - return __import__("Crypto.Hash." + hash_name, globals(), locals(), ["new"]) - - -class FIPS_PKCS1_Verify_Tests(unittest.TestCase): - - def shortDescription(self): - return "FIPS PKCS1 Tests (Verify)" - - def test_can_sign(self): - test_public_key = RSA.generate(1024).public_key() - verifier = pkcs1_15.new(test_public_key) - self.assertEqual(verifier.can_sign(), False) - - -class FIPS_PKCS1_Verify_Tests_KAT(unittest.TestCase): - pass - - -test_vectors_verify = load_test_vectors(("Signature", "PKCS1-v1.5"), - "SigVer15_186-3.rsp", - "Signature Verification 186-3", - {'shaalg': lambda x: x, - 'd': lambda x: int(x), - 'result': lambda x: x}) or [] - - -for count, tv in enumerate(test_vectors_verify): - if isinstance(tv, str): - continue - if hasattr(tv, "n"): - modulus = tv.n - continue - - hash_module = load_hash_by_name(tv.shaalg.upper()) - hash_obj = hash_module.new(tv.msg) - public_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e)]) # type: ignore - verifier = pkcs1_15.new(public_key) - - def positive_test(self, hash_obj=hash_obj, verifier=verifier, signature=tv.s): - verifier.verify(hash_obj, signature) - - def negative_test(self, hash_obj=hash_obj, verifier=verifier, signature=tv.s): - self.assertRaises(ValueError, verifier.verify, hash_obj, signature) - - if tv.result == 'f': - setattr(FIPS_PKCS1_Verify_Tests_KAT, "test_negative_%d" % count, negative_test) - else: - setattr(FIPS_PKCS1_Verify_Tests_KAT, "test_positive_%d" % count, positive_test) - - -class FIPS_PKCS1_Sign_Tests(unittest.TestCase): - - def shortDescription(self): - return "FIPS PKCS1 Tests (Sign)" - - def test_can_sign(self): - test_private_key = RSA.generate(1024) - signer = pkcs1_15.new(test_private_key) - self.assertEqual(signer.can_sign(), True) - - -class FIPS_PKCS1_Sign_Tests_KAT(unittest.TestCase): - pass - - -test_vectors_sign = load_test_vectors(("Signature", "PKCS1-v1.5"), - "SigGen15_186-2.txt", - "Signature Generation 186-2", - {'shaalg': lambda x: x}) or [] - -test_vectors_sign += load_test_vectors(("Signature", "PKCS1-v1.5"), - "SigGen15_186-3.txt", - "Signature Generation 186-3", - {'shaalg': lambda x: x}) or [] - -for count, tv in enumerate(test_vectors_sign): - if isinstance(tv, str): - continue - if hasattr(tv, "n"): - modulus = tv.n - continue - if hasattr(tv, "e"): - private_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e, tv.d)]) # type: ignore - signer = pkcs1_15.new(private_key) - continue - - hash_module = load_hash_by_name(tv.shaalg.upper()) - hash_obj = hash_module.new(tv.msg) - - def new_test(self, hash_obj=hash_obj, signer=signer, result=tv.s): - signature = signer.sign(hash_obj) - self.assertEqual(signature, result) - - setattr(FIPS_PKCS1_Sign_Tests_KAT, "test_%d" % count, new_test) - - -class PKCS1_15_NoParams(unittest.TestCase): - """Verify that PKCS#1 v1.5 signatures pass even without NULL parameters in - the algorithm identifier (PyCrypto/LP bug #1119552).""" - - rsakey = """-----BEGIN RSA PRIVATE KEY----- - MIIBOwIBAAJBAL8eJ5AKoIsjURpcEoGubZMxLD7+kT+TLr7UkvEtFrRhDDKMtuII - q19FrL4pUIMymPMSLBn3hJLe30Dw48GQM4UCAwEAAQJACUSDEp8RTe32ftq8IwG8 - Wojl5mAd1wFiIOrZ/Uv8b963WJOJiuQcVN29vxU5+My9GPZ7RA3hrDBEAoHUDPrI - OQIhAPIPLz4dphiD9imAkivY31Rc5AfHJiQRA7XixTcjEkojAiEAyh/pJHks/Mlr - +rdPNEpotBjfV4M4BkgGAA/ipcmaAjcCIQCHvhwwKVBLzzTscT2HeUdEeBMoiXXK - JACAr3sJQJGxIQIgarRp+m1WSKV1MciwMaTOnbU7wxFs9DP1pva76lYBzgUCIQC9 - n0CnZCJ6IZYqSt0H5N7+Q+2Ro64nuwV/OSQfM6sBwQ== - -----END RSA PRIVATE KEY-----""" - - msg = b"This is a test\x0a" - - # PKCS1 v1.5 signature of the message computed using SHA-1. - # The digestAlgorithm SEQUENCE does NOT contain the NULL parameter. - sig_str = "a287a13517f716e72fb14eea8e33a8db4a4643314607e7ca3e3e28"\ - "1893db74013dda8b855fd99f6fecedcb25fcb7a434f35cd0a101f8"\ - "b19348e0bd7b6f152dfc" - signature = unhexlify(sig_str) - - def runTest(self): - verifier = pkcs1_15.new(RSA.importKey(self.rsakey)) - hashed = SHA1.new(self.msg) - verifier.verify(hashed, self.signature) - - -class PKCS1_Legacy_Module_Tests(unittest.TestCase): - """Verify that the legacy module Crypto.Signature.PKCS1_v1_5 - behaves as expected. The only difference is that the verify() - method returns True/False and does not raise exceptions.""" - - def shortDescription(self): - return "Test legacy Crypto.Signature.PKCS1_v1_5" - - def runTest(self): - key = RSA.importKey(PKCS1_15_NoParams.rsakey) - hashed = SHA1.new(b"Test") - good_signature = PKCS1_v1_5.new(key).sign(hashed) - verifier = PKCS1_v1_5.new(key.public_key()) - - self.assertEqual(verifier.verify(hashed, good_signature), True) - - # Flip a few bits in the signature - bad_signature = strxor(good_signature, bchr(1) * len(good_signature)) - self.assertEqual(verifier.verify(hashed, bad_signature), False) - - -class PKCS1_All_Hashes_Tests(unittest.TestCase): - - def shortDescription(self): - return "Test PKCS#1v1.5 signature in combination with all hashes" - - def runTest(self): - - key = RSA.generate(1024) - signer = pkcs1_15.new(key) - hash_names = ("MD2", "MD4", "MD5", "RIPEMD160", "SHA1", - "SHA224", "SHA256", "SHA384", "SHA512", - "SHA3_224", "SHA3_256", "SHA3_384", "SHA3_512") - - for name in hash_names: - hashed = load_hash_by_name(name).new(b"Test") - signer.sign(hashed) - - from Crypto.Hash import BLAKE2b, BLAKE2s - for hash_size in (20, 32, 48, 64): - hashed_b = BLAKE2b.new(digest_bytes=hash_size, data=b"Test") - signer.sign(hashed_b) - for hash_size in (16, 20, 28, 32): - hashed_s = BLAKE2s.new(digest_bytes=hash_size, data=b"Test") - signer.sign(hashed_s) - - -class TestVectorsWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._id = "None" - - def setUp(self): - self.tv = [] - self.add_tests("rsa_sig_gen_misc_test.json") - self.add_tests("rsa_signature_2048_sha224_test.json") - self.add_tests("rsa_signature_2048_sha256_test.json") - self.add_tests("rsa_signature_2048_sha384_test.json") - self.add_tests("rsa_signature_2048_sha3_224_test.json") - self.add_tests("rsa_signature_2048_sha3_256_test.json") - self.add_tests("rsa_signature_2048_sha3_384_test.json") - self.add_tests("rsa_signature_2048_sha3_512_test.json") - self.add_tests("rsa_signature_2048_sha512_test.json") - self.add_tests("rsa_signature_2048_sha512_224_test.json") - self.add_tests("rsa_signature_2048_sha512_256_test.json") - self.add_tests("rsa_signature_3072_sha256_test.json") - self.add_tests("rsa_signature_3072_sha384_test.json") - self.add_tests("rsa_signature_3072_sha3_256_test.json") - self.add_tests("rsa_signature_3072_sha3_384_test.json") - self.add_tests("rsa_signature_3072_sha3_512_test.json") - self.add_tests("rsa_signature_3072_sha512_test.json") - self.add_tests("rsa_signature_3072_sha512_256_test.json") - self.add_tests("rsa_signature_4096_sha384_test.json") - self.add_tests("rsa_signature_4096_sha512_test.json") - self.add_tests("rsa_signature_4096_sha512_256_test.json") - self.add_tests("rsa_signature_test.json") - - def add_tests(self, filename): - - def filter_rsa(group): - return RSA.import_key(group['keyPem']) - - def filter_sha(group): - hash_name = group['sha'] - if hash_name == "SHA-512": - return SHA512 - elif hash_name == "SHA-512/224": - return SHA512.new(truncate="224") - elif hash_name == "SHA-512/256": - return SHA512.new(truncate="256") - elif hash_name == "SHA3-512": - return SHA3_512 - elif hash_name == "SHA-384": - return SHA384 - elif hash_name == "SHA3-384": - return SHA3_384 - elif hash_name == "SHA-256": - return SHA256 - elif hash_name == "SHA3-256": - return SHA3_256 - elif hash_name == "SHA-224": - return SHA224 - elif hash_name == "SHA3-224": - return SHA3_224 - elif hash_name == "SHA-1": - return SHA1 - else: - raise ValueError("Unknown hash algorithm: " + hash_name) - - def filter_type(group): - type_name = group['type'] - if type_name not in ("RsassaPkcs1Verify", "RsassaPkcs1Generate"): - raise ValueError("Unknown type name " + type_name) - - result = load_test_vectors_wycheproof(("Signature", "wycheproof"), - filename, - "Wycheproof PKCS#1v1.5 signature (%s)" % filename, - group_tag={'rsa_key': filter_rsa, - 'hash_mod': filter_sha, - 'type': filter_type}) - return result - - def shortDescription(self): - return self._id - - 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_verify(self, tv): - self._id = "Wycheproof RSA PKCS$#1 Test #" + str(tv.id) - - hashed_msg = tv.hash_module.new(tv.msg) - signer = pkcs1_15.new(tv.key) - try: - signature = signer.verify(hashed_msg, tv.sig) - except ValueError as e: - if tv.warning: - return - assert not tv.valid - else: - assert tv.valid - self.warn(tv) - - def runTest(self): - for tv in self.tv: - self.test_verify(tv) - - -def get_tests(config={}): - wycheproof_warnings = config.get('wycheproof_warnings') - - tests = [] - tests += list_test_cases(FIPS_PKCS1_Verify_Tests) - tests += list_test_cases(FIPS_PKCS1_Sign_Tests) - tests += list_test_cases(PKCS1_15_NoParams) - tests += list_test_cases(PKCS1_Legacy_Module_Tests) - tests += list_test_cases(PKCS1_All_Hashes_Tests) - tests += [ TestVectorsWycheproof(wycheproof_warnings) ] - - if config.get('slow_tests'): - tests += list_test_cases(FIPS_PKCS1_Verify_Tests_KAT) - tests += list_test_cases(FIPS_PKCS1_Sign_Tests_KAT) - - return tests - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/Signature/test_pss.py b/Crypto/SelfTest/Signature/test_pss.py deleted file mode 100644 index 535474b..0000000 --- a/Crypto/SelfTest/Signature/test_pss.py +++ /dev/null @@ -1,377 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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 Crypto.Util.py3compat import b, bchr -from Crypto.Util.number import bytes_to_long -from Crypto.Util.strxor import strxor -from Crypto.SelfTest.st_common import list_test_cases -from Crypto.SelfTest.loader import load_test_vectors, load_test_vectors_wycheproof - -from Crypto.Hash import SHA1, SHA224, SHA256, SHA384, SHA512 -from Crypto.PublicKey import RSA -from Crypto.Signature import pss -from Crypto.Signature import PKCS1_PSS - -from Crypto.Signature.pss import MGF1 - - -def load_hash_by_name(hash_name): - return __import__("Crypto.Hash." + hash_name, globals(), locals(), ["new"]) - - -class PRNG(object): - - def __init__(self, stream): - self.stream = stream - self.idx = 0 - - def __call__(self, rnd_size): - result = self.stream[self.idx:self.idx + rnd_size] - self.idx += rnd_size - return result - - -class PSS_Tests(unittest.TestCase): - - rsa_key = b'-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAsvI34FgiTK8+txBvmooNGpNwk23YTU51dwNZi5yha3W4lA/Q\nvcZrDalkmD7ekWQwnduxVKa6pRSI13KBgeUOIqJoGXSWhntEtY3FEwvWOHW5AE7Q\njUzTzCiYT6TVaCcpa/7YLai+p6ai2g5f5Zfh4jSawa9uYeuggFygQq4IVW796MgV\nyqxYMM/arEj+/sKz3Viua9Rp9fFosertCYCX4DUTgW0mX9bwEnEOgjSI3pLOPXz1\n8vx+DRZS5wMCmwCUa0sKonLn3cAUPq+sGix7+eo7T0Z12MU8ud7IYVX/75r3cXiF\nPaYE2q8Le0kgOApIXbb+x74x0rNgyIh1yGygkwIDAQABAoIBABz4t1A0pLT6qHI2\nEIOaNz3mwhK0dZEqkz0GB1Dhtoax5ATgvKCFB98J3lYB08IBURe1snOsnMpOVUtg\naBRSM+QqnCUG6bnzKjAkuFP5liDE+oNQv1YpKp9CsUovuzdmI8Au3ewihl+ZTIN2\nUVNYMEOR1b5m+z2SSwWNOYsiJwpBrT7zkpdlDyjat7FiiPhMMIMXjhQFVxURMIcB\njUBtPzGvV/PG90cVDWi1wRGeeP1dDqti/jsnvykQ15KW1MqGrpeNKRmDdTy/Ucl1\nWIoYklKw3U456lgZ/rDTDB818+Tlnk35z4yF7d5ANPM8CKfqOPcnO1BCKVFzf4eq\n54wvUtkCgYEA1Zv2lp06l7rXMsvNtyYQjbFChezRDRnPwZmN4NCdRtTgGG1G0Ryd\nYz6WWoPGqZp0b4LAaaHd3W2GTcpXF8WXMKfMX1W+tMAxMozfsXRKMcHoypwuS5wT\nfJRXJCG4pvd57AB0iVUEJW2we+uGKU5Zxcx//id2nXGCpoRyViIplQsCgYEA1nVC\neHupHChht0Fh4N09cGqZHZzuwXjOUMzR3Vsfz+4WzVS3NvIgN4g5YgmQFOeKwo5y\niRq5yvubcNdFvf85eHWClg0zPAyxJCVUWigCrrOanGEhJo6re4idJvNVzu4Ucg0v\n6B3SJ1HsCda+ZSNz24bSyqRep8A+RoAaoVSFx5kCgYEAn3RvXPs9s+obnqWYiPF3\nRe5etE6Vt2vfNKwFxx6zaR6bsmBQjuUHcABWiHb6I71S0bMPI0tbrWGG8ibrYKl1\nNTLtUvVVCOS3VP7oNTWT9RTFTAnOXU7DFSo+6o/poWn3r36ff6zhDXeWWMr2OXtt\ndEQ1/2lCGEGVv+v61eVmmQUCgYABFHITPTwqwiFL1O5zPWnzyPWgaovhOYSAb6eW\n38CXQXGn8wdBJZL39J2lWrr4//l45VK6UgIhfYbY2JynSkO10ZGow8RARygVMILu\nOUlaK9lZdDvAf/NpGdUAvzTtZ9F+iYZ2OsA2JnlzyzsGM1l//3vMPWukmJk3ral0\nqoJJ8QKBgGRG3eVHnIegBbFVuMDp2NTcfuSuDVUQ1fGAwtPiFa8u81IodJnMk2pq\niXu2+0ytNA/M+SVrAnE2AgIzcaJbtr0p2srkuVM7KMWnG1vWFNjtXN8fAhf/joOv\nD+NmPL/N4uE57e40tbiU/H7KdyZaDt+5QiTmdhuyAe6CBjKsF2jy\n-----END RSA PRIVATE KEY-----' - msg = b'AAA' - tag = b'\x00[c5\xd8\xb0\x8b!D\x81\x83\x07\xc0\xdd\xb9\xb4\xb2`\x92\xe7\x02\xf1\xe1P\xea\xc3\xf0\xe3>\xddX5\xdd\x8e\xc5\x89\xef\xf3\xc2\xdc\xfeP\x02\x7f\x12+\xc9\xaf\xbb\xec\xfe\xb0\xa5\xb9\x08\x11P\x8fL\xee5\x9b\xb0k{=_\xd2\x14\xfb\x01R\xb7\xfe\x14}b\x03\x8d5Y\x89~}\xfc\xf2l\xd01-\xbd\xeb\x11\xcdV\x11\xe9l\x19k/o5\xa2\x0f\x15\xe7Q$\t=\xec\x1dAB\x19\xa5P\x9a\xaf\xa3G\x86"\xd6~\xf0j\xfcqkbs\x13\x84b\xe4\xbdm(\xed`\xa4F\xfb\x8f.\xe1\x8c)/_\x9eS\x98\xa4v\xb8\xdc\xfe\xf7/D\x18\x19\xb3T\x97:\xe2\x96s\xe8<\xa2\xb4\xb9\xf8/' - - def test_positive_1(self): - key = RSA.import_key(self.rsa_key) - h = SHA256.new(self.msg) - verifier = pss.new(key) - verifier.verify(h, self.tag) - - def test_negative_1(self): - key = RSA.import_key(self.rsa_key) - h = SHA256.new(self.msg + b'A') - verifier = pss.new(key) - tag = bytearray(self.tag) - self.assertRaises(ValueError, verifier.verify, h, tag) - - def test_negative_2(self): - key = RSA.import_key(self.rsa_key) - h = SHA256.new(self.msg) - verifier = pss.new(key, salt_bytes=1000) - tag = bytearray(self.tag) - self.assertRaises(ValueError, verifier.verify, h, tag) - - -class FIPS_PKCS1_Verify_Tests(unittest.TestCase): - - def shortDescription(self): - return "FIPS PKCS1 Tests (Verify)" - - def verify_positive(self, hashmod, message, public_key, salt, signature): - prng = PRNG(salt) - hashed = hashmod.new(message) - verifier = pss.new(public_key, salt_bytes=len(salt), rand_func=prng) - verifier.verify(hashed, signature) - - def verify_negative(self, hashmod, message, public_key, salt, signature): - prng = PRNG(salt) - hashed = hashmod.new(message) - verifier = pss.new(public_key, salt_bytes=len(salt), rand_func=prng) - self.assertRaises(ValueError, verifier.verify, hashed, signature) - - def test_can_sign(self): - test_public_key = RSA.generate(1024).public_key() - verifier = pss.new(test_public_key) - self.assertEqual(verifier.can_sign(), False) - - -class FIPS_PKCS1_Verify_Tests_KAT(unittest.TestCase): - pass - - -test_vectors_verify = load_test_vectors(("Signature", "PKCS1-PSS"), - "SigVerPSS_186-3.rsp", - "Signature Verification 186-3", - {'shaalg': lambda x: x, - 'result': lambda x: x}) or [] - - -for count, tv in enumerate(test_vectors_verify): - if isinstance(tv, str): - continue - if hasattr(tv, "n"): - modulus = tv.n - continue - if hasattr(tv, "p"): - continue - - hash_module = load_hash_by_name(tv.shaalg.upper()) - hash_obj = hash_module.new(tv.msg) - public_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e)]) # type: ignore - if tv.saltval != b("\x00"): - prng = PRNG(tv.saltval) - verifier = pss.new(public_key, salt_bytes=len(tv.saltval), rand_func=prng) - else: - verifier = pss.new(public_key, salt_bytes=0) - - def positive_test(self, hash_obj=hash_obj, verifier=verifier, signature=tv.s): - verifier.verify(hash_obj, signature) - - def negative_test(self, hash_obj=hash_obj, verifier=verifier, signature=tv.s): - self.assertRaises(ValueError, verifier.verify, hash_obj, signature) - - if tv.result == 'p': - setattr(FIPS_PKCS1_Verify_Tests_KAT, "test_positive_%d" % count, positive_test) - else: - setattr(FIPS_PKCS1_Verify_Tests_KAT, "test_negative_%d" % count, negative_test) - - -class FIPS_PKCS1_Sign_Tests(unittest.TestCase): - - def shortDescription(self): - return "FIPS PKCS1 Tests (Sign)" - - def test_can_sign(self): - test_private_key = RSA.generate(1024) - signer = pss.new(test_private_key) - self.assertEqual(signer.can_sign(), True) - - -class FIPS_PKCS1_Sign_Tests_KAT(unittest.TestCase): - pass - - -test_vectors_sign = load_test_vectors(("Signature", "PKCS1-PSS"), - "SigGenPSS_186-2.txt", - "Signature Generation 186-2", - {'shaalg': lambda x: x}) or [] - -test_vectors_sign += load_test_vectors(("Signature", "PKCS1-PSS"), - "SigGenPSS_186-3.txt", - "Signature Generation 186-3", - {'shaalg': lambda x: x}) or [] - -for count, tv in enumerate(test_vectors_sign): - if isinstance(tv, str): - continue - if hasattr(tv, "n"): - modulus = tv.n - continue - if hasattr(tv, "e"): - private_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e, tv.d)]) # type: ignore - continue - - hash_module = load_hash_by_name(tv.shaalg.upper()) - hash_obj = hash_module.new(tv.msg) - if tv.saltval != b("\x00"): - prng = PRNG(tv.saltval) - signer = pss.new(private_key, salt_bytes=len(tv.saltval), rand_func=prng) - else: - signer = pss.new(private_key, salt_bytes=0) - - def new_test(self, hash_obj=hash_obj, signer=signer, result=tv.s): - signature = signer.sign(hash_obj) - self.assertEqual(signature, result) - - setattr(FIPS_PKCS1_Sign_Tests_KAT, "test_%d" % count, new_test) - - -class PKCS1_Legacy_Module_Tests(unittest.TestCase): - """Verify that the legacy module Crypto.Signature.PKCS1_PSS - behaves as expected. The only difference is that the verify() - method returns True/False and does not raise exceptions.""" - - def shortDescription(self): - return "Test legacy Crypto.Signature.PKCS1_PSS" - - def runTest(self): - key = RSA.generate(1024) - hashed = SHA1.new(b("Test")) - good_signature = PKCS1_PSS.new(key).sign(hashed) - verifier = PKCS1_PSS.new(key.public_key()) - - self.assertEqual(verifier.verify(hashed, good_signature), True) - - # Flip a few bits in the signature - bad_signature = strxor(good_signature, bchr(1) * len(good_signature)) - self.assertEqual(verifier.verify(hashed, bad_signature), False) - - -class PKCS1_All_Hashes_Tests(unittest.TestCase): - - def shortDescription(self): - return "Test PKCS#1 PSS signature in combination with all hashes" - - def runTest(self): - - key = RSA.generate(1280) - signer = pss.new(key) - hash_names = ("MD2", "MD4", "MD5", "RIPEMD160", "SHA1", - "SHA224", "SHA256", "SHA384", "SHA512", - "SHA3_224", "SHA3_256", "SHA3_384", "SHA3_512") - - for name in hash_names: - hashed = load_hash_by_name(name).new(b("Test")) - signer.sign(hashed) - - from Crypto.Hash import BLAKE2b, BLAKE2s - for hash_size in (20, 32, 48, 64): - hashed_b = BLAKE2b.new(digest_bytes=hash_size, data=b("Test")) - signer.sign(hashed_b) - for hash_size in (16, 20, 28, 32): - hashed_s = BLAKE2s.new(digest_bytes=hash_size, data=b("Test")) - signer.sign(hashed_s) - - -def get_hash_module(hash_name): - if hash_name == "SHA-512": - hash_module = SHA512 - elif hash_name == "SHA-512/224": - hash_module = SHA512.new(truncate="224") - elif hash_name == "SHA-512/256": - hash_module = SHA512.new(truncate="256") - elif hash_name == "SHA-384": - hash_module = SHA384 - elif hash_name == "SHA-256": - hash_module = SHA256 - elif hash_name == "SHA-224": - hash_module = SHA224 - elif hash_name == "SHA-1": - hash_module = SHA1 - else: - raise ValueError("Unknown hash algorithm: " + hash_name) - return hash_module - - -class TestVectorsPSSWycheproof(unittest.TestCase): - - def __init__(self, wycheproof_warnings): - unittest.TestCase.__init__(self) - self._wycheproof_warnings = wycheproof_warnings - self._id = "None" - - def add_tests(self, filename): - - def filter_rsa(group): - return RSA.import_key(group['keyPem']) - - def filter_sha(group): - return get_hash_module(group['sha']) - - def filter_type(group): - type_name = group['type'] - if type_name not in ("RsassaPssVerify", ): - raise ValueError("Unknown type name " + type_name) - - def filter_slen(group): - return group['sLen'] - - def filter_mgf(group): - mgf = group['mgf'] - if mgf not in ("MGF1", ): - raise ValueError("Unknown MGF " + mgf) - mgf1_hash = get_hash_module(group['mgfSha']) - - def mgf(x, y, mh=mgf1_hash): - return MGF1(x, y, mh) - - return mgf - - result = load_test_vectors_wycheproof(("Signature", "wycheproof"), - filename, - "Wycheproof PSS signature (%s)" % filename, - group_tag={'key': filter_rsa, - 'hash_module': filter_sha, - 'sLen': filter_slen, - 'mgf': filter_mgf, - 'type': filter_type}) - return result - - def setUp(self): - self.tv = [] - self.add_tests("rsa_pss_2048_sha1_mgf1_20_test.json") - self.add_tests("rsa_pss_2048_sha256_mgf1_0_test.json") - self.add_tests("rsa_pss_2048_sha256_mgf1_32_test.json") - self.add_tests("rsa_pss_2048_sha512_256_mgf1_28_test.json") - self.add_tests("rsa_pss_2048_sha512_256_mgf1_32_test.json") - self.add_tests("rsa_pss_3072_sha256_mgf1_32_test.json") - self.add_tests("rsa_pss_4096_sha256_mgf1_32_test.json") - self.add_tests("rsa_pss_4096_sha512_mgf1_32_test.json") - self.add_tests("rsa_pss_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_verify(self, tv): - self._id = "Wycheproof RSA PSS Test #%d (%s)" % (tv.id, tv.comment) - - hashed_msg = tv.hash_module.new(tv.msg) - signer = pss.new(tv.key, mask_func=tv.mgf, salt_bytes=tv.sLen) - try: - signature = signer.verify(hashed_msg, tv.sig) - except ValueError as e: - if tv.warning: - return - assert not tv.valid - else: - assert tv.valid - self.warn(tv) - - def runTest(self): - for tv in self.tv: - self.test_verify(tv) - - -def get_tests(config={}): - wycheproof_warnings = config.get('wycheproof_warnings') - - tests = [] - tests += list_test_cases(PSS_Tests) - tests += list_test_cases(FIPS_PKCS1_Verify_Tests) - tests += list_test_cases(FIPS_PKCS1_Sign_Tests) - tests += list_test_cases(PKCS1_Legacy_Module_Tests) - tests += list_test_cases(PKCS1_All_Hashes_Tests) - - if config.get('slow_tests'): - tests += list_test_cases(FIPS_PKCS1_Verify_Tests_KAT) - tests += list_test_cases(FIPS_PKCS1_Sign_Tests_KAT) - - tests += [TestVectorsPSSWycheproof(wycheproof_warnings)] - - return tests - - -if __name__ == '__main__': - def suite(): - return unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/Util/__init__.py b/Crypto/SelfTest/Util/__init__.py deleted file mode 100644 index ee993db..0000000 --- a/Crypto/SelfTest/Util/__init__.py +++ /dev/null @@ -1,46 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Util/__init__.py: Self-test for utility modules -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# 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 utility modules""" - -__revision__ = "$Id$" - -import os - -def get_tests(config={}): - tests = [] - from Crypto.SelfTest.Util import test_number; tests += test_number.get_tests(config=config) - from Crypto.SelfTest.Util import test_Counter; tests += test_Counter.get_tests(config=config) - from Crypto.SelfTest.Util import test_Padding; tests += test_Padding.get_tests(config=config) - from Crypto.SelfTest.Util import test_strxor; tests += test_strxor.get_tests(config=config) - from Crypto.SelfTest.Util import test_asn1; tests += test_asn1.get_tests(config=config) - from Crypto.SelfTest.Util import test_rfc1751; tests += test_rfc1751.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: diff --git a/Crypto/SelfTest/Util/__pycache__/__init__.cpython-36.pyc b/Crypto/SelfTest/Util/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index 2a9a2ad..0000000 Binary files a/Crypto/SelfTest/Util/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Util/__pycache__/test_Counter.cpython-36.pyc b/Crypto/SelfTest/Util/__pycache__/test_Counter.cpython-36.pyc deleted file mode 100644 index b383938..0000000 Binary files a/Crypto/SelfTest/Util/__pycache__/test_Counter.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Util/__pycache__/test_Padding.cpython-36.pyc b/Crypto/SelfTest/Util/__pycache__/test_Padding.cpython-36.pyc deleted file mode 100644 index 46f7c57..0000000 Binary files a/Crypto/SelfTest/Util/__pycache__/test_Padding.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Util/__pycache__/test_asn1.cpython-36.pyc b/Crypto/SelfTest/Util/__pycache__/test_asn1.cpython-36.pyc deleted file mode 100644 index b3e9b3a..0000000 Binary files a/Crypto/SelfTest/Util/__pycache__/test_asn1.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Util/__pycache__/test_number.cpython-36.pyc b/Crypto/SelfTest/Util/__pycache__/test_number.cpython-36.pyc deleted file mode 100644 index d1250ba..0000000 Binary files a/Crypto/SelfTest/Util/__pycache__/test_number.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Util/__pycache__/test_rfc1751.cpython-36.pyc b/Crypto/SelfTest/Util/__pycache__/test_rfc1751.cpython-36.pyc deleted file mode 100644 index 609f792..0000000 Binary files a/Crypto/SelfTest/Util/__pycache__/test_rfc1751.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Util/__pycache__/test_strxor.cpython-36.pyc b/Crypto/SelfTest/Util/__pycache__/test_strxor.cpython-36.pyc deleted file mode 100644 index c17b687..0000000 Binary files a/Crypto/SelfTest/Util/__pycache__/test_strxor.cpython-36.pyc and /dev/null differ diff --git a/Crypto/SelfTest/Util/test_Counter.py b/Crypto/SelfTest/Util/test_Counter.py deleted file mode 100644 index 8837a32..0000000 --- a/Crypto/SelfTest/Util/test_Counter.py +++ /dev/null @@ -1,67 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Util/test_Counter: Self-test for the Crypto.Util.Counter module -# -# Written in 2009 by Dwayne C. Litzenberger -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-tests for Crypto.Util.Counter""" - -from Crypto.Util.py3compat import * - -import unittest - -class CounterTests(unittest.TestCase): - def setUp(self): - global Counter - from Crypto.Util import Counter - - def test_BE(self): - """Big endian""" - c = Counter.new(128) - c = Counter.new(128, little_endian=False) - - def test_LE(self): - """Little endian""" - c = Counter.new(128, little_endian=True) - - def test_nbits(self): - c = Counter.new(nbits=128) - self.assertRaises(ValueError, Counter.new, 129) - - def test_prefix(self): - c = Counter.new(128, prefix=b("xx")) - - def test_suffix(self): - c = Counter.new(128, suffix=b("xx")) - - def test_iv(self): - c = Counter.new(128, initial_value=2) - self.assertRaises(ValueError, Counter.new, 16, initial_value=0x1FFFF) - -def get_tests(config={}): - from Crypto.SelfTest.st_common import list_test_cases - return list_test_cases(CounterTests) - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') - -# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/Crypto/SelfTest/Util/test_Padding.py b/Crypto/SelfTest/Util/test_Padding.py deleted file mode 100644 index 4634659..0000000 --- a/Crypto/SelfTest/Util/test_Padding.py +++ /dev/null @@ -1,154 +0,0 @@ -# -# SelfTest/Util/test_Padding.py: Self-test for padding functions -# -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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 as uh - -from Crypto.Util.py3compat import * -from Crypto.SelfTest.st_common import list_test_cases -from Crypto.Util.Padding import pad, unpad - -class PKCS7_Tests(unittest.TestCase): - - def test1(self): - padded = pad(b(""), 4) - self.failUnless(padded == uh(b("04040404"))) - padded = pad(b(""), 4, 'pkcs7') - self.failUnless(padded == uh(b("04040404"))) - back = unpad(padded, 4) - self.failUnless(back == b("")) - - def test2(self): - padded = pad(uh(b("12345678")), 4) - self.failUnless(padded == uh(b("1234567804040404"))) - back = unpad(padded, 4) - self.failUnless(back == uh(b("12345678"))) - - def test3(self): - padded = pad(uh(b("123456")), 4) - self.failUnless(padded == uh(b("12345601"))) - back = unpad(padded, 4) - self.failUnless(back == uh(b("123456"))) - - def test4(self): - padded = pad(uh(b("1234567890")), 4) - self.failUnless(padded == uh(b("1234567890030303"))) - back = unpad(padded, 4) - self.failUnless(back == uh(b("1234567890"))) - - def testn1(self): - self.assertRaises(ValueError, pad, uh(b("12")), 4, 'pkcs8') - - def testn2(self): - self.assertRaises(ValueError, unpad, b("\0\0\0"), 4) - self.assertRaises(ValueError, unpad, b(""), 4) - - def testn3(self): - self.assertRaises(ValueError, unpad, b("123456\x02"), 4) - self.assertRaises(ValueError, unpad, b("123456\x00"), 4) - self.assertRaises(ValueError, unpad, b("123456\x05\x05\x05\x05\x05"), 4) - -class X923_Tests(unittest.TestCase): - - def test1(self): - padded = pad(b(""), 4, 'x923') - self.failUnless(padded == uh(b("00000004"))) - back = unpad(padded, 4, 'x923') - self.failUnless(back == b("")) - - def test2(self): - padded = pad(uh(b("12345678")), 4, 'x923') - self.failUnless(padded == uh(b("1234567800000004"))) - back = unpad(padded, 4, 'x923') - self.failUnless(back == uh(b("12345678"))) - - def test3(self): - padded = pad(uh(b("123456")), 4, 'x923') - self.failUnless(padded == uh(b("12345601"))) - back = unpad(padded, 4, 'x923') - self.failUnless(back == uh(b("123456"))) - - def test4(self): - padded = pad(uh(b("1234567890")), 4, 'x923') - self.failUnless(padded == uh(b("1234567890000003"))) - back = unpad(padded, 4, 'x923') - self.failUnless(back == uh(b("1234567890"))) - - def testn1(self): - self.assertRaises(ValueError, unpad, b("123456\x02"), 4, 'x923') - self.assertRaises(ValueError, unpad, b("123456\x00"), 4, 'x923') - self.assertRaises(ValueError, unpad, b("123456\x00\x00\x00\x00\x05"), 4, 'x923') - self.assertRaises(ValueError, unpad, b(""), 4, 'x923') - -class ISO7816_Tests(unittest.TestCase): - - def test1(self): - padded = pad(b(""), 4, 'iso7816') - self.failUnless(padded == uh(b("80000000"))) - back = unpad(padded, 4, 'iso7816') - self.failUnless(back == b("")) - - def test2(self): - padded = pad(uh(b("12345678")), 4, 'iso7816') - self.failUnless(padded == uh(b("1234567880000000"))) - back = unpad(padded, 4, 'iso7816') - self.failUnless(back == uh(b("12345678"))) - - def test3(self): - padded = pad(uh(b("123456")), 4, 'iso7816') - self.failUnless(padded == uh(b("12345680"))) - #import pdb; pdb.set_trace() - back = unpad(padded, 4, 'iso7816') - self.failUnless(back == uh(b("123456"))) - - def test4(self): - padded = pad(uh(b("1234567890")), 4, 'iso7816') - self.failUnless(padded == uh(b("1234567890800000"))) - back = unpad(padded, 4, 'iso7816') - self.failUnless(back == uh(b("1234567890"))) - - def testn1(self): - self.assertRaises(ValueError, unpad, b("123456\x81"), 4, 'iso7816') - self.assertRaises(ValueError, unpad, b(""), 4, 'iso7816') - -def get_tests(config={}): - tests = [] - tests += list_test_cases(PKCS7_Tests) - tests += list_test_cases(X923_Tests) - tests += list_test_cases(ISO7816_Tests) - return tests - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') - diff --git a/Crypto/SelfTest/Util/test_asn1.py b/Crypto/SelfTest/Util/test_asn1.py deleted file mode 100644 index 368e47d..0000000 --- a/Crypto/SelfTest/Util/test_asn1.py +++ /dev/null @@ -1,784 +0,0 @@ -# -# SelfTest/Util/test_asn.py: Self-test for the Crypto.Util.asn1 module -# -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -"""Self-tests for Crypto.Util.asn1""" - -import unittest - -from Crypto.Util.py3compat import * -from Crypto.Util.asn1 import (DerObject, DerSetOf, DerInteger, - DerBitString, - DerObjectId, DerNull, DerOctetString, - DerSequence) - -class DerObjectTests(unittest.TestCase): - - def testObjInit1(self): - # Fail with invalid tag format (must be 1 byte) - self.assertRaises(ValueError, DerObject, b('\x00\x99')) - # Fail with invalid implicit tag (must be <0x1F) - self.assertRaises(ValueError, DerObject, 0x1F) - - # ------ - - def testObjEncode1(self): - # No payload - der = DerObject(b('\x02')) - self.assertEquals(der.encode(), b('\x02\x00')) - # Small payload (primitive) - der.payload = b('\x45') - self.assertEquals(der.encode(), b('\x02\x01\x45')) - # Invariant - self.assertEquals(der.encode(), b('\x02\x01\x45')) - # Initialize with numerical tag - der = DerObject(0x04) - der.payload = b('\x45') - self.assertEquals(der.encode(), b('\x04\x01\x45')) - # Initialize with constructed type - der = DerObject(b('\x10'), constructed=True) - self.assertEquals(der.encode(), b('\x30\x00')) - - def testObjEncode2(self): - # Initialize with payload - der = DerObject(0x03, b('\x12\x12')) - self.assertEquals(der.encode(), b('\x03\x02\x12\x12')) - - def testObjEncode3(self): - # Long payload - der = DerObject(b('\x10')) - der.payload = b("0")*128 - self.assertEquals(der.encode(), b('\x10\x81\x80' + "0"*128)) - - def testObjEncode4(self): - # Implicit tags (constructed) - der = DerObject(0x10, implicit=1, constructed=True) - der.payload = b('ppll') - self.assertEquals(der.encode(), b('\xa1\x04ppll')) - # Implicit tags (primitive) - der = DerObject(0x02, implicit=0x1E, constructed=False) - der.payload = b('ppll') - self.assertEquals(der.encode(), b('\x9E\x04ppll')) - - def testObjEncode5(self): - # Encode type with explicit tag - der = DerObject(0x10, explicit=5) - der.payload = b("xxll") - self.assertEqual(der.encode(), b("\xa5\x06\x10\x04xxll")) - - # ----- - - def testObjDecode1(self): - # Decode short payload - der = DerObject(0x02) - der.decode(b('\x02\x02\x01\x02')) - self.assertEquals(der.payload, b("\x01\x02")) - self.assertEquals(der._tag_octet, 0x02) - - def testObjDecode2(self): - # Decode long payload - der = DerObject(0x02) - der.decode(b('\x02\x81\x80' + "1"*128)) - self.assertEquals(der.payload, b("1")*128) - self.assertEquals(der._tag_octet, 0x02) - - def testObjDecode3(self): - # Decode payload with too much data gives error - der = DerObject(0x02) - self.assertRaises(ValueError, der.decode, b('\x02\x02\x01\x02\xFF')) - # Decode payload with too little data gives error - der = DerObject(0x02) - self.assertRaises(ValueError, der.decode, b('\x02\x02\x01')) - - def testObjDecode4(self): - # Decode implicit tag (primitive) - der = DerObject(0x02, constructed=False, implicit=0xF) - self.assertRaises(ValueError, der.decode, b('\x02\x02\x01\x02')) - der.decode(b('\x8F\x01\x00')) - self.assertEquals(der.payload, b('\x00')) - # Decode implicit tag (constructed) - der = DerObject(0x02, constructed=True, implicit=0xF) - self.assertRaises(ValueError, der.decode, b('\x02\x02\x01\x02')) - der.decode(b('\xAF\x01\x00')) - self.assertEquals(der.payload, b('\x00')) - - def testObjDecode5(self): - # Decode payload with unexpected tag gives error - der = DerObject(0x02) - self.assertRaises(ValueError, der.decode, b('\x03\x02\x01\x02')) - - def testObjDecode6(self): - # Arbitrary DER object - der = DerObject() - der.decode(b('\x65\x01\x88')) - self.assertEquals(der._tag_octet, 0x65) - self.assertEquals(der.payload, b('\x88')) - - def testObjDecode7(self): - # Decode explicit tag - der = DerObject(0x10, explicit=5) - der.decode(b("\xa5\x06\x10\x04xxll")) - self.assertEquals(der._inner_tag_octet, 0x10) - self.assertEquals(der.payload, b('xxll')) - - # Explicit tag may be 0 - der = DerObject(0x10, explicit=0) - der.decode(b("\xa0\x06\x10\x04xxll")) - self.assertEquals(der._inner_tag_octet, 0x10) - self.assertEquals(der.payload, b('xxll')) - - def testObjDecode8(self): - # Verify that decode returns the object - der = DerObject(0x02) - self.assertEqual(der, der.decode(b('\x02\x02\x01\x02'))) - -class DerIntegerTests(unittest.TestCase): - - def testInit1(self): - der = DerInteger(1) - self.assertEquals(der.encode(), b('\x02\x01\x01')) - - def testEncode1(self): - # Single-byte integers - # Value 0 - der = DerInteger(0) - self.assertEquals(der.encode(), b('\x02\x01\x00')) - # Value 1 - der = DerInteger(1) - self.assertEquals(der.encode(), b('\x02\x01\x01')) - # Value 127 - der = DerInteger(127) - self.assertEquals(der.encode(), b('\x02\x01\x7F')) - - def testEncode2(self): - # Multi-byte integers - # Value 128 - der = DerInteger(128) - self.assertEquals(der.encode(), b('\x02\x02\x00\x80')) - # Value 0x180 - der = DerInteger(0x180) - self.assertEquals(der.encode(), b('\x02\x02\x01\x80')) - # One very long integer - der = DerInteger(2**2048) - self.assertEquals(der.encode(), - b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00')) - - def testEncode3(self): - # Negative integers - # Value -1 - der = DerInteger(-1) - self.assertEquals(der.encode(), b('\x02\x01\xFF')) - # Value -128 - der = DerInteger(-128) - self.assertEquals(der.encode(), b('\x02\x01\x80')) - # Value - der = DerInteger(-87873) - self.assertEquals(der.encode(), b('\x02\x03\xFE\xA8\xBF')) - - def testEncode4(self): - # Explicit encoding - number = DerInteger(0x34, explicit=3) - self.assertEquals(number.encode(), b('\xa3\x03\x02\x01\x34')) - - # ----- - - def testDecode1(self): - # Single-byte integer - der = DerInteger() - # Value 0 - der.decode(b('\x02\x01\x00')) - self.assertEquals(der.value, 0) - # Value 1 - der.decode(b('\x02\x01\x01')) - self.assertEquals(der.value, 1) - # Value 127 - der.decode(b('\x02\x01\x7F')) - self.assertEquals(der.value, 127) - - def testDecode2(self): - # Multi-byte integer - der = DerInteger() - # Value 0x180L - der.decode(b('\x02\x02\x01\x80')) - self.assertEquals(der.value,0x180) - # One very long integer - der.decode( - b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00')) - self.assertEquals(der.value,2**2048) - - def testDecode3(self): - # Negative integer - der = DerInteger() - # Value -1 - der.decode(b('\x02\x01\xFF')) - self.assertEquals(der.value, -1) - # Value -32768 - der.decode(b('\x02\x02\x80\x00')) - self.assertEquals(der.value, -32768) - - def testDecode5(self): - # We still accept BER integer format - der = DerInteger() - # Redundant leading zeroes - der.decode(b('\x02\x02\x00\x01')) - self.assertEquals(der.value, 1) - # Redundant leading 0xFF - der.decode(b('\x02\x02\xFF\xFF')) - self.assertEquals(der.value, -1) - # Empty payload - der.decode(b('\x02\x00')) - self.assertEquals(der.value, 0) - - def testDecode6(self): - # Explicit encoding - number = DerInteger(explicit=3) - number.decode(b('\xa3\x03\x02\x01\x34')) - self.assertEquals(number.value, 0x34) - - def testDecode7(self): - # Verify decode returns the DerInteger - der = DerInteger() - self.assertEquals(der, der.decode(b('\x02\x01\x7F'))) - - ### - - def testStrict1(self): - number = DerInteger() - - number.decode(b'\x02\x02\x00\x01') - number.decode(b'\x02\x02\x00\x7F') - self.assertRaises(ValueError, number.decode, b'\x02\x02\x00\x01', strict=True) - self.assertRaises(ValueError, number.decode, b'\x02\x02\x00\x7F', strict=True) - - ### - - def testErrDecode1(self): - # Wide length field - der = DerInteger() - self.assertRaises(ValueError, der.decode, b('\x02\x81\x01\x01')) - - -class DerSequenceTests(unittest.TestCase): - - def testInit1(self): - der = DerSequence([1, DerInteger(2), b('0\x00')]) - self.assertEquals(der.encode(), b('0\x08\x02\x01\x01\x02\x01\x020\x00')) - - def testEncode1(self): - # Empty sequence - der = DerSequence() - self.assertEquals(der.encode(), b('0\x00')) - self.failIf(der.hasOnlyInts()) - # One single-byte integer (zero) - der.append(0) - self.assertEquals(der.encode(), b('0\x03\x02\x01\x00')) - self.assertEquals(der.hasInts(),1) - self.assertEquals(der.hasInts(False),1) - self.failUnless(der.hasOnlyInts()) - self.failUnless(der.hasOnlyInts(False)) - # Invariant - self.assertEquals(der.encode(), b('0\x03\x02\x01\x00')) - - def testEncode2(self): - # Indexing - der = DerSequence() - der.append(0) - der[0] = 1 - self.assertEquals(len(der),1) - self.assertEquals(der[0],1) - self.assertEquals(der[-1],1) - self.assertEquals(der.encode(), b('0\x03\x02\x01\x01')) - # - der[:] = [1] - self.assertEquals(len(der),1) - self.assertEquals(der[0],1) - self.assertEquals(der.encode(), b('0\x03\x02\x01\x01')) - - def testEncode3(self): - # One multi-byte integer (non-zero) - der = DerSequence() - der.append(0x180) - self.assertEquals(der.encode(), b('0\x04\x02\x02\x01\x80')) - - def testEncode4(self): - # One very long integer - der = DerSequence() - der.append(2**2048) - self.assertEquals(der.encode(), b('0\x82\x01\x05')+ - b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00')) - - def testEncode5(self): - der = DerSequence() - der += 1 - der += b('\x30\x00') - self.assertEquals(der.encode(), b('\x30\x05\x02\x01\x01\x30\x00')) - - def testEncode6(self): - # Two positive integers - der = DerSequence() - der.append(0x180) - der.append(0xFF) - self.assertEquals(der.encode(), b('0\x08\x02\x02\x01\x80\x02\x02\x00\xff')) - self.failUnless(der.hasOnlyInts()) - self.failUnless(der.hasOnlyInts(False)) - # Two mixed integers - der = DerSequence() - der.append(2) - der.append(-2) - self.assertEquals(der.encode(), b('0\x06\x02\x01\x02\x02\x01\xFE')) - self.assertEquals(der.hasInts(), 1) - self.assertEquals(der.hasInts(False), 2) - self.failIf(der.hasOnlyInts()) - self.failUnless(der.hasOnlyInts(False)) - # - der.append(0x01) - der[1:] = [9,8] - self.assertEquals(len(der),3) - self.assertEqual(der[1:],[9,8]) - self.assertEqual(der[1:-1],[9]) - self.assertEquals(der.encode(), b('0\x09\x02\x01\x02\x02\x01\x09\x02\x01\x08')) - - def testEncode7(self): - # One integer and another type (already encoded) - der = DerSequence() - der.append(0x180) - der.append(b('0\x03\x02\x01\x05')) - self.assertEquals(der.encode(), b('0\x09\x02\x02\x01\x800\x03\x02\x01\x05')) - self.failIf(der.hasOnlyInts()) - - def testEncode8(self): - # One integer and another type (yet to encode) - der = DerSequence() - der.append(0x180) - der.append(DerSequence([5])) - self.assertEquals(der.encode(), b('0\x09\x02\x02\x01\x800\x03\x02\x01\x05')) - self.failIf(der.hasOnlyInts()) - - #### - - def testDecode1(self): - # Empty sequence - der = DerSequence() - der.decode(b('0\x00')) - self.assertEquals(len(der),0) - # One single-byte integer (zero) - der.decode(b('0\x03\x02\x01\x00')) - self.assertEquals(len(der),1) - self.assertEquals(der[0],0) - # Invariant - der.decode(b('0\x03\x02\x01\x00')) - self.assertEquals(len(der),1) - self.assertEquals(der[0],0) - - def testDecode2(self): - # One single-byte integer (non-zero) - der = DerSequence() - der.decode(b('0\x03\x02\x01\x7f')) - self.assertEquals(len(der),1) - self.assertEquals(der[0],127) - - def testDecode4(self): - # One very long integer - der = DerSequence() - der.decode(b('0\x82\x01\x05')+ - b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+ - b('\x00\x00\x00\x00\x00\x00\x00\x00\x00')) - self.assertEquals(len(der),1) - self.assertEquals(der[0],2**2048) - - def testDecode6(self): - # Two integers - der = DerSequence() - der.decode(b('0\x08\x02\x02\x01\x80\x02\x02\x00\xff')) - self.assertEquals(len(der),2) - self.assertEquals(der[0],0x180) - self.assertEquals(der[1],0xFF) - - def testDecode7(self): - # One integer and 2 other types - der = DerSequence() - der.decode(b('0\x0A\x02\x02\x01\x80\x24\x02\xb6\x63\x12\x00')) - self.assertEquals(len(der),3) - self.assertEquals(der[0],0x180) - self.assertEquals(der[1],b('\x24\x02\xb6\x63')) - self.assertEquals(der[2],b('\x12\x00')) - - def testDecode8(self): - # Only 2 other types - der = DerSequence() - der.decode(b('0\x06\x24\x02\xb6\x63\x12\x00')) - self.assertEquals(len(der),2) - self.assertEquals(der[0],b('\x24\x02\xb6\x63')) - self.assertEquals(der[1],b('\x12\x00')) - self.assertEquals(der.hasInts(), 0) - self.assertEquals(der.hasInts(False), 0) - self.failIf(der.hasOnlyInts()) - self.failIf(der.hasOnlyInts(False)) - - def testDecode9(self): - # Verify that decode returns itself - der = DerSequence() - self.assertEqual(der, der.decode(b('0\x06\x24\x02\xb6\x63\x12\x00'))) - - ### - - def testErrDecode1(self): - # Not a sequence - der = DerSequence() - self.assertRaises(ValueError, der.decode, b('')) - self.assertRaises(ValueError, der.decode, b('\x00')) - self.assertRaises(ValueError, der.decode, b('\x30')) - - def testErrDecode2(self): - der = DerSequence() - # Too much data - self.assertRaises(ValueError, der.decode, b('\x30\x00\x00')) - - def testErrDecode3(self): - # Wrong length format - der = DerSequence() - # Missing length in sub-item - self.assertRaises(ValueError, der.decode, b('\x30\x04\x02\x01\x01\x00')) - # Valid BER, but invalid DER length - self.assertRaises(ValueError, der.decode, b('\x30\x81\x03\x02\x01\x01')) - self.assertRaises(ValueError, der.decode, b('\x30\x04\x02\x81\x01\x01')) - - def test_expected_nr_elements(self): - der_bin = DerSequence([1, 2, 3]).encode() - - DerSequence().decode(der_bin, nr_elements=3) - DerSequence().decode(der_bin, nr_elements=(2,3)) - self.assertRaises(ValueError, DerSequence().decode, der_bin, nr_elements=1) - self.assertRaises(ValueError, DerSequence().decode, der_bin, nr_elements=(4,5)) - - def test_expected_only_integers(self): - - der_bin1 = DerSequence([1, 2, 3]).encode() - der_bin2 = DerSequence([1, 2, DerSequence([3, 4])]).encode() - - DerSequence().decode(der_bin1, only_ints_expected=True) - DerSequence().decode(der_bin1, only_ints_expected=False) - DerSequence().decode(der_bin2, only_ints_expected=False) - self.assertRaises(ValueError, DerSequence().decode, der_bin2, only_ints_expected=True) - - -class DerOctetStringTests(unittest.TestCase): - - def testInit1(self): - der = DerOctetString(b('\xFF')) - self.assertEquals(der.encode(), b('\x04\x01\xFF')) - - def testEncode1(self): - # Empty sequence - der = DerOctetString() - self.assertEquals(der.encode(), b('\x04\x00')) - # Small payload - der.payload = b('\x01\x02') - self.assertEquals(der.encode(), b('\x04\x02\x01\x02')) - - #### - - def testDecode1(self): - # Empty sequence - der = DerOctetString() - der.decode(b('\x04\x00')) - self.assertEquals(der.payload, b('')) - # Small payload - der.decode(b('\x04\x02\x01\x02')) - self.assertEquals(der.payload, b('\x01\x02')) - - def testDecode2(self): - # Verify that decode returns the object - der = DerOctetString() - self.assertEqual(der, der.decode(b('\x04\x00'))) - - def testErrDecode1(self): - # No leftovers allowed - der = DerOctetString() - self.assertRaises(ValueError, der.decode, b('\x04\x01\x01\xff')) - -class DerNullTests(unittest.TestCase): - - def testEncode1(self): - der = DerNull() - self.assertEquals(der.encode(), b('\x05\x00')) - - #### - - def testDecode1(self): - # Empty sequence - der = DerNull() - self.assertEquals(der, der.decode(b('\x05\x00'))) - -class DerObjectIdTests(unittest.TestCase): - - def testInit1(self): - der = DerObjectId("1.1") - self.assertEquals(der.encode(), b('\x06\x01)')) - - def testEncode1(self): - der = DerObjectId('1.2.840.113549.1.1.1') - self.assertEquals(der.encode(), b('\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01')) - # - der = DerObjectId() - der.value = '1.2.840.113549.1.1.1' - self.assertEquals(der.encode(), b('\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01')) - - #### - - def testDecode1(self): - # Empty sequence - der = DerObjectId() - der.decode(b('\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01')) - self.assertEquals(der.value, '1.2.840.113549.1.1.1') - - def testDecode2(self): - # Verify that decode returns the object - der = DerObjectId() - self.assertEquals(der, - der.decode(b('\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01'))) - - def testDecode3(self): - der = DerObjectId() - der.decode(b('\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x00\x01')) - self.assertEquals(der.value, '1.2.840.113549.1.0.1') - - -class DerBitStringTests(unittest.TestCase): - - def testInit1(self): - der = DerBitString(b("\xFF")) - self.assertEquals(der.encode(), b('\x03\x02\x00\xFF')) - - def testInit2(self): - der = DerBitString(DerInteger(1)) - self.assertEquals(der.encode(), b('\x03\x04\x00\x02\x01\x01')) - - def testEncode1(self): - # Empty sequence - der = DerBitString() - self.assertEquals(der.encode(), b('\x03\x01\x00')) - # Small payload - der = DerBitString(b('\x01\x02')) - self.assertEquals(der.encode(), b('\x03\x03\x00\x01\x02')) - # Small payload - der = DerBitString() - der.value = b('\x01\x02') - self.assertEquals(der.encode(), b('\x03\x03\x00\x01\x02')) - - #### - - def testDecode1(self): - # Empty sequence - der = DerBitString() - der.decode(b('\x03\x00')) - self.assertEquals(der.value, b('')) - # Small payload - der.decode(b('\x03\x03\x00\x01\x02')) - self.assertEquals(der.value, b('\x01\x02')) - - def testDecode2(self): - # Verify that decode returns the object - der = DerBitString() - self.assertEquals(der, der.decode(b('\x03\x00'))) - - -class DerSetOfTests(unittest.TestCase): - - def testInit1(self): - der = DerSetOf([DerInteger(1), DerInteger(2)]) - self.assertEquals(der.encode(), b('1\x06\x02\x01\x01\x02\x01\x02')) - - def testEncode1(self): - # Empty set - der = DerSetOf() - self.assertEquals(der.encode(), b('1\x00')) - # One single-byte integer (zero) - der.add(0) - self.assertEquals(der.encode(), b('1\x03\x02\x01\x00')) - # Invariant - self.assertEquals(der.encode(), b('1\x03\x02\x01\x00')) - - def testEncode2(self): - # Two integers - der = DerSetOf() - der.add(0x180) - der.add(0xFF) - self.assertEquals(der.encode(), b('1\x08\x02\x02\x00\xff\x02\x02\x01\x80')) - # Initialize with integers - der = DerSetOf([0x180, 0xFF]) - self.assertEquals(der.encode(), b('1\x08\x02\x02\x00\xff\x02\x02\x01\x80')) - - def testEncode3(self): - # One integer and another type (no matter what it is) - der = DerSetOf() - der.add(0x180) - self.assertRaises(ValueError, der.add, b('\x00\x02\x00\x00')) - - def testEncode4(self): - # Only non integers - der = DerSetOf() - der.add(b('\x01\x00')) - der.add(b('\x01\x01\x01')) - self.assertEquals(der.encode(), b('1\x05\x01\x00\x01\x01\x01')) - - #### - - def testDecode1(self): - # Empty sequence - der = DerSetOf() - der.decode(b('1\x00')) - self.assertEquals(len(der),0) - # One single-byte integer (zero) - der.decode(b('1\x03\x02\x01\x00')) - self.assertEquals(len(der),1) - self.assertEquals(list(der),[0]) - - def testDecode2(self): - # Two integers - der = DerSetOf() - der.decode(b('1\x08\x02\x02\x01\x80\x02\x02\x00\xff')) - self.assertEquals(len(der),2) - l = list(der) - self.failUnless(0x180 in l) - self.failUnless(0xFF in l) - - def testDecode3(self): - # One integer and 2 other types - der = DerSetOf() - #import pdb; pdb.set_trace() - self.assertRaises(ValueError, der.decode, - b('0\x0A\x02\x02\x01\x80\x24\x02\xb6\x63\x12\x00')) - - def testDecode4(self): - # Verify that decode returns the object - der = DerSetOf() - self.assertEquals(der, - der.decode(b('1\x08\x02\x02\x01\x80\x02\x02\x00\xff'))) - - ### - - def testErrDecode1(self): - # No leftovers allowed - der = DerSetOf() - self.assertRaises(ValueError, der.decode, - b('1\x08\x02\x02\x01\x80\x02\x02\x00\xff\xAA')) - -def get_tests(config={}): - from Crypto.SelfTest.st_common import list_test_cases - listTests = [] - listTests += list_test_cases(DerObjectTests) - listTests += list_test_cases(DerIntegerTests) - listTests += list_test_cases(DerSequenceTests) - listTests += list_test_cases(DerOctetStringTests) - listTests += list_test_cases(DerNullTests) - listTests += list_test_cases(DerObjectIdTests) - listTests += list_test_cases(DerBitStringTests) - listTests += list_test_cases(DerSetOfTests) - return listTests - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') - -# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/Crypto/SelfTest/Util/test_number.py b/Crypto/SelfTest/Util/test_number.py deleted file mode 100644 index 13f9d19..0000000 --- a/Crypto/SelfTest/Util/test_number.py +++ /dev/null @@ -1,144 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/Util/test_number.py: Self-test for parts of the Crypto.Util.number module -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self-tests for (some of) Crypto.Util.number""" - -from Crypto.Util.py3compat import * - -import unittest - -class MyError(Exception): - """Dummy exception used for tests""" - -# NB: In some places, we compare tuples instead of just output values so that -# if any inputs cause a test failure, we'll be able to tell which ones. - -class MiscTests(unittest.TestCase): - def setUp(self): - global number, math - from Crypto.Util import number - import math - - def test_ceil_div(self): - """Util.number.ceil_div""" - self.assertRaises(TypeError, number.ceil_div, "1", 1) - self.assertRaises(ZeroDivisionError, number.ceil_div, 1, 0) - self.assertRaises(ZeroDivisionError, number.ceil_div, -1, 0) - - # b = 1 - self.assertEqual(0, number.ceil_div(0, 1)) - self.assertEqual(1, number.ceil_div(1, 1)) - self.assertEqual(2, number.ceil_div(2, 1)) - self.assertEqual(3, number.ceil_div(3, 1)) - - # b = 2 - self.assertEqual(0, number.ceil_div(0, 2)) - self.assertEqual(1, number.ceil_div(1, 2)) - self.assertEqual(1, number.ceil_div(2, 2)) - self.assertEqual(2, number.ceil_div(3, 2)) - self.assertEqual(2, number.ceil_div(4, 2)) - self.assertEqual(3, number.ceil_div(5, 2)) - - # b = 3 - self.assertEqual(0, number.ceil_div(0, 3)) - self.assertEqual(1, number.ceil_div(1, 3)) - self.assertEqual(1, number.ceil_div(2, 3)) - self.assertEqual(1, number.ceil_div(3, 3)) - self.assertEqual(2, number.ceil_div(4, 3)) - self.assertEqual(2, number.ceil_div(5, 3)) - self.assertEqual(2, number.ceil_div(6, 3)) - self.assertEqual(3, number.ceil_div(7, 3)) - - # b = 4 - self.assertEqual(0, number.ceil_div(0, 4)) - self.assertEqual(1, number.ceil_div(1, 4)) - self.assertEqual(1, number.ceil_div(2, 4)) - self.assertEqual(1, number.ceil_div(3, 4)) - self.assertEqual(1, number.ceil_div(4, 4)) - self.assertEqual(2, number.ceil_div(5, 4)) - self.assertEqual(2, number.ceil_div(6, 4)) - self.assertEqual(2, number.ceil_div(7, 4)) - self.assertEqual(2, number.ceil_div(8, 4)) - self.assertEqual(3, number.ceil_div(9, 4)) - - def test_getStrongPrime(self): - """Util.number.getStrongPrime""" - self.assertRaises(ValueError, number.getStrongPrime, 256) - self.assertRaises(ValueError, number.getStrongPrime, 513) - bits = 512 - x = number.getStrongPrime(bits) - self.assertNotEqual(x % 2, 0) - self.assertEqual(x > (1 << bits-1)-1, 1) - self.assertEqual(x < (1 << bits), 1) - e = 2**16+1 - x = number.getStrongPrime(bits, e) - self.assertEqual(number.GCD(x-1, e), 1) - self.assertNotEqual(x % 2, 0) - self.assertEqual(x > (1 << bits-1)-1, 1) - self.assertEqual(x < (1 << bits), 1) - e = 2**16+2 - x = number.getStrongPrime(bits, e) - self.assertEqual(number.GCD((x-1)>>1, e), 1) - self.assertNotEqual(x % 2, 0) - self.assertEqual(x > (1 << bits-1)-1, 1) - self.assertEqual(x < (1 << bits), 1) - - def test_isPrime(self): - """Util.number.isPrime""" - self.assertEqual(number.isPrime(-3), False) # Regression test: negative numbers should not be prime - self.assertEqual(number.isPrime(-2), False) # Regression test: negative numbers should not be prime - self.assertEqual(number.isPrime(1), False) # Regression test: isPrime(1) caused some versions of PyCrypto to crash. - self.assertEqual(number.isPrime(2), True) - self.assertEqual(number.isPrime(3), True) - self.assertEqual(number.isPrime(4), False) - self.assertEqual(number.isPrime(2**1279-1), True) - self.assertEqual(number.isPrime(-(2**1279-1)), False) # Regression test: negative numbers should not be prime - # test some known gmp pseudo-primes taken from - # http://www.trnicely.net/misc/mpzspsp.html - for composite in (43 * 127 * 211, 61 * 151 * 211, 15259 * 30517, - 346141 * 692281, 1007119 * 2014237, 3589477 * 7178953, - 4859419 * 9718837, 2730439 * 5460877, - 245127919 * 490255837, 963939391 * 1927878781, - 4186358431 * 8372716861, 1576820467 * 3153640933): - self.assertEqual(number.isPrime(int(composite)), False) - - def test_size(self): - self.assertEqual(number.size(2),2) - self.assertEqual(number.size(3),2) - self.assertEqual(number.size(0xa2),8) - self.assertEqual(number.size(0xa2ba40),8*3) - self.assertEqual(number.size(0xa2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65e394c69d4b3c05a1e8fadda27edb2a42bc000fe888b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea904b1ec102b2e4de7751222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5), 1024) - self.assertRaises(ValueError, number.size, -1) - - -def get_tests(config={}): - from Crypto.SelfTest.st_common import list_test_cases - tests = list_test_cases(MiscTests) - return tests - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') - -# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/Crypto/SelfTest/Util/test_rfc1751.py b/Crypto/SelfTest/Util/test_rfc1751.py deleted file mode 100644 index af0aa2b..0000000 --- a/Crypto/SelfTest/Util/test_rfc1751.py +++ /dev/null @@ -1,38 +0,0 @@ -import unittest - -import binascii -from Crypto.Util.RFC1751 import key_to_english, english_to_key - - -class RFC1751_Tests(unittest.TestCase): - - def test1(self): - data = [ - ('EB33F77EE73D4053', 'TIDE ITCH SLOW REIN RULE MOT'), - ('CCAC2AED591056BE4F90FD441C534766', 'RASH BUSH MILK LOOK BAD BRIM AVID GAFF BAIT ROT POD LOVE'), - ('EFF81F9BFBC65350920CDD7416DE8009', 'TROD MUTE TAIL WARM CHAR KONG HAAG CITY BORE O TEAL AWL') - ] - - for key_hex, words in data: - key_bin = binascii.a2b_hex(key_hex) - - w2 = key_to_english(key_bin) - self.assertEqual(w2, words) - - k2 = english_to_key(words) - self.assertEqual(k2, key_bin) - - def test_error_key_to_english(self): - - self.assertRaises(ValueError, key_to_english, b'0' * 7) - - -def get_tests(config={}): - from Crypto.SelfTest.st_common import list_test_cases - tests = list_test_cases(RFC1751_Tests) - return tests - - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/Util/test_strxor.py b/Crypto/SelfTest/Util/test_strxor.py deleted file mode 100644 index c91d38f..0000000 --- a/Crypto/SelfTest/Util/test_strxor.py +++ /dev/null @@ -1,280 +0,0 @@ -# -# SelfTest/Util/test_strxor.py: Self-test for XORing -# -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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, hexlify - -from Crypto.SelfTest.st_common import list_test_cases -from Crypto.Util.strxor import strxor, strxor_c - - -class StrxorTests(unittest.TestCase): - - def test1(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term2 = unhexlify(b"383d4ba020573314395b") - result = unhexlify(b"c70ed123c59a7fcb6f12") - self.assertEqual(strxor(term1, term2), result) - self.assertEqual(strxor(term2, term1), result) - - def test2(self): - es = b"" - self.assertEqual(strxor(es, es), es) - - def test3(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - all_zeros = b"\x00" * len(term1) - self.assertEqual(strxor(term1, term1), all_zeros) - - def test_wrong_length(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term2 = unhexlify(b"ff339a83e5cd4cdf564990") - self.assertRaises(ValueError, strxor, term1, term2) - - def test_bytearray(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term1_ba = bytearray(term1) - term2 = unhexlify(b"383d4ba020573314395b") - result = unhexlify(b"c70ed123c59a7fcb6f12") - - self.assertEqual(strxor(term1_ba, term2), result) - - def test_memoryview(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term1_mv = memoryview(term1) - term2 = unhexlify(b"383d4ba020573314395b") - result = unhexlify(b"c70ed123c59a7fcb6f12") - - self.assertEqual(strxor(term1_mv, term2), result) - - def test_output_bytearray(self): - """Verify result can be stored in pre-allocated memory""" - - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term2 = unhexlify(b"383d4ba020573314395b") - original_term1 = term1[:] - original_term2 = term2[:] - expected_xor = unhexlify(b"c70ed123c59a7fcb6f12") - output = bytearray(len(term1)) - - result = strxor(term1, term2, output=output) - - self.assertEqual(result, None) - self.assertEqual(output, expected_xor) - self.assertEqual(term1, original_term1) - self.assertEqual(term2, original_term2) - - def test_output_memoryview(self): - """Verify result can be stored in pre-allocated memory""" - - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term2 = unhexlify(b"383d4ba020573314395b") - original_term1 = term1[:] - original_term2 = term2[:] - expected_xor = unhexlify(b"c70ed123c59a7fcb6f12") - output = memoryview(bytearray(len(term1))) - - result = strxor(term1, term2, output=output) - - self.assertEqual(result, None) - self.assertEqual(output, expected_xor) - self.assertEqual(term1, original_term1) - self.assertEqual(term2, original_term2) - - def test_output_overlapping_bytearray(self): - """Verify result can be stored in overlapping memory""" - - term1 = bytearray(unhexlify(b"ff339a83e5cd4cdf5649")) - term2 = unhexlify(b"383d4ba020573314395b") - original_term2 = term2[:] - expected_xor = unhexlify(b"c70ed123c59a7fcb6f12") - - result = strxor(term1, term2, output=term1) - - self.assertEqual(result, None) - self.assertEqual(term1, expected_xor) - self.assertEqual(term2, original_term2) - - def test_output_overlapping_memoryview(self): - """Verify result can be stored in overlapping memory""" - - term1 = memoryview(bytearray(unhexlify(b"ff339a83e5cd4cdf5649"))) - term2 = unhexlify(b"383d4ba020573314395b") - original_term2 = term2[:] - expected_xor = unhexlify(b"c70ed123c59a7fcb6f12") - - result = strxor(term1, term2, output=term1) - - self.assertEqual(result, None) - self.assertEqual(term1, expected_xor) - self.assertEqual(term2, original_term2) - - def test_output_ro_bytes(self): - """Verify result cannot be stored in read-only memory""" - - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term2 = unhexlify(b"383d4ba020573314395b") - - self.assertRaises(TypeError, strxor, term1, term2, output=term1) - - def test_output_ro_memoryview(self): - """Verify result cannot be stored in read-only memory""" - - term1 = memoryview(unhexlify(b"ff339a83e5cd4cdf5649")) - term2 = unhexlify(b"383d4ba020573314395b") - - self.assertRaises(TypeError, strxor, term1, term2, output=term1) - - def test_output_incorrect_length(self): - """Verify result cannot be stored in memory of incorrect length""" - - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term2 = unhexlify(b"383d4ba020573314395b") - output = bytearray(len(term1) - 1) - - self.assertRaises(ValueError, strxor, term1, term2, output=output) - - -class Strxor_cTests(unittest.TestCase): - - def test1(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - result = unhexlify(b"be72dbc2a48c0d9e1708") - self.assertEqual(strxor_c(term1, 65), result) - - def test2(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - self.assertEqual(strxor_c(term1, 0), term1) - - def test3(self): - self.assertEqual(strxor_c(b"", 90), b"") - - def test_wrong_range(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - self.assertRaises(ValueError, strxor_c, term1, -1) - self.assertRaises(ValueError, strxor_c, term1, 256) - - def test_bytearray(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term1_ba = bytearray(term1) - result = unhexlify(b"be72dbc2a48c0d9e1708") - - self.assertEqual(strxor_c(term1_ba, 65), result) - - def test_memoryview(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - term1_mv = memoryview(term1) - result = unhexlify(b"be72dbc2a48c0d9e1708") - - self.assertEqual(strxor_c(term1_mv, 65), result) - - def test_output_bytearray(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - original_term1 = term1[:] - expected_result = unhexlify(b"be72dbc2a48c0d9e1708") - output = bytearray(len(term1)) - - result = strxor_c(term1, 65, output=output) - - self.assertEqual(result, None) - self.assertEqual(output, expected_result) - self.assertEqual(term1, original_term1) - - def test_output_memoryview(self): - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - original_term1 = term1[:] - expected_result = unhexlify(b"be72dbc2a48c0d9e1708") - output = memoryview(bytearray(len(term1))) - - result = strxor_c(term1, 65, output=output) - - self.assertEqual(result, None) - self.assertEqual(output, expected_result) - self.assertEqual(term1, original_term1) - - def test_output_overlapping_bytearray(self): - """Verify result can be stored in overlapping memory""" - - term1 = bytearray(unhexlify(b"ff339a83e5cd4cdf5649")) - expected_xor = unhexlify(b"be72dbc2a48c0d9e1708") - - result = strxor_c(term1, 65, output=term1) - - self.assertEqual(result, None) - self.assertEqual(term1, expected_xor) - - def test_output_overlapping_memoryview(self): - """Verify result can be stored in overlapping memory""" - - term1 = memoryview(bytearray(unhexlify(b"ff339a83e5cd4cdf5649"))) - expected_xor = unhexlify(b"be72dbc2a48c0d9e1708") - - result = strxor_c(term1, 65, output=term1) - - self.assertEqual(result, None) - self.assertEqual(term1, expected_xor) - - def test_output_ro_bytes(self): - """Verify result cannot be stored in read-only memory""" - - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - - self.assertRaises(TypeError, strxor_c, term1, 65, output=term1) - - def test_output_ro_memoryview(self): - """Verify result cannot be stored in read-only memory""" - - term1 = memoryview(unhexlify(b"ff339a83e5cd4cdf5649")) - term2 = unhexlify(b"383d4ba020573314395b") - - self.assertRaises(TypeError, strxor_c, term1, 65, output=term1) - - def test_output_incorrect_length(self): - """Verify result cannot be stored in memory of incorrect length""" - - term1 = unhexlify(b"ff339a83e5cd4cdf5649") - output = bytearray(len(term1) - 1) - - self.assertRaises(ValueError, strxor_c, term1, 65, output=output) - - -def get_tests(config={}): - tests = [] - tests += list_test_cases(StrxorTests) - tests += list_test_cases(Strxor_cTests) - return tests - - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') diff --git a/Crypto/SelfTest/__init__.py b/Crypto/SelfTest/__init__.py deleted file mode 100644 index bc34f4a..0000000 --- a/Crypto/SelfTest/__init__.py +++ /dev/null @@ -1,97 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/__init__.py: Self-test for PyCrypto -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Self tests - -These tests should perform quickly and can ideally be used every time an -application runs. -""" - -__revision__ = "$Id$" - -import sys -import unittest -from Crypto.Util.py3compat import BytesIO - -class SelfTestError(Exception): - def __init__(self, message, result): - Exception.__init__(self, message, result) - self.message = message - self.result = result - -def run(module=None, verbosity=0, stream=None, tests=None, config=None, **kwargs): - """Execute self-tests. - - This raises SelfTestError if any test is unsuccessful. - - You may optionally pass in a sub-module of SelfTest if you only want to - perform some of the tests. For example, the following would test only the - hash modules: - - Crypto.SelfTest.run(Crypto.SelfTest.Hash) - - """ - - if config is None: - config = {} - suite = unittest.TestSuite() - if module is None: - if tests is None: - tests = get_tests(config=config) - suite.addTests(tests) - else: - if tests is None: - suite.addTests(module.get_tests(config=config)) - else: - raise ValueError("'module' and 'tests' arguments are mutually exclusive") - if stream is None: - kwargs['stream'] = BytesIO() - else: - kwargs['stream'] = stream - runner = unittest.TextTestRunner(verbosity=verbosity, **kwargs) - result = runner.run(suite) - if not result.wasSuccessful(): - if stream is None: - sys.stderr.write(kwargs['stream'].getvalue()) - raise SelfTestError("Self-test failed", result) - return result - -def get_tests(config={}): - tests = [] - from Crypto.SelfTest import Cipher; tests += Cipher.get_tests(config=config) - from Crypto.SelfTest import Hash; tests += Hash.get_tests(config=config) - from Crypto.SelfTest import Protocol; tests += Protocol.get_tests(config=config) - from Crypto.SelfTest import PublicKey; tests += PublicKey.get_tests(config=config) - from Crypto.SelfTest import Random; tests += Random.get_tests(config=config) - from Crypto.SelfTest import Util; tests += Util.get_tests(config=config) - from Crypto.SelfTest import Signature; tests += Signature.get_tests(config=config) - from Crypto.SelfTest import IO; tests += IO.get_tests(config=config) - from Crypto.SelfTest import Math; tests += Math.get_tests(config=config) - return tests - -if __name__ == '__main__': - suite = lambda: unittest.TestSuite(get_tests()) - unittest.main(defaultTest='suite') - -# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/Crypto/SelfTest/__main__.py b/Crypto/SelfTest/__main__.py deleted file mode 100644 index 9ab0912..0000000 --- a/Crypto/SelfTest/__main__.py +++ /dev/null @@ -1,38 +0,0 @@ -#! /usr/bin/env python -# -# __main__.py : Stand-along loader for PyCryptodome test suite -# -# =================================================================== -# 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 sys - -from Crypto import SelfTest - -slow_tests = not "--skip-slow-tests" in sys.argv -if not slow_tests: - print("Skipping slow tests") - -wycheproof_warnings = "--wycheproof-warnings" in sys.argv -if wycheproof_warnings: - print("Printing Wycheproof warnings") - -config = {'slow_tests' : slow_tests, 'wycheproof_warnings' : wycheproof_warnings } -SelfTest.run(stream=sys.stdout, verbosity=1, config=config) diff --git a/Crypto/SelfTest/loader.py b/Crypto/SelfTest/loader.py deleted file mode 100644 index 18be270..0000000 --- a/Crypto/SelfTest/loader.py +++ /dev/null @@ -1,206 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2016, Legrandin -# 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 json -import errno -import binascii -import warnings -from binascii import unhexlify -from Crypto.Util.py3compat import FileNotFoundError - - -try: - import pycryptodome_test_vectors # type: ignore - test_vectors_available = True -except ImportError: - test_vectors_available = False - - -def _load_tests(dir_comps, file_in, description, conversions): - """Load and parse a test vector file - - Return a list of objects, one per group of adjacent - KV lines or for a single line in the form "[.*]". - - For a group of lines, the object has one attribute per line. - """ - - line_number = 0 - results = [] - - class TestVector(object): - def __init__(self, description, count): - self.desc = description - self.count = count - self.others = [] - - test_vector = None - count = 0 - new_group = True - - while True: - line_number += 1 - line = file_in.readline() - if not line: - if test_vector is not None: - results.append(test_vector) - break - line = line.strip() - - # Skip comments and empty lines - if line.startswith('#') or not line: - new_group = True - continue - - if line.startswith("["): - if test_vector is not None: - results.append(test_vector) - test_vector = None - results.append(line) - continue - - if new_group: - count += 1 - new_group = False - if test_vector is not None: - results.append(test_vector) - test_vector = TestVector("%s (#%d)" % (description, count), count) - - res = re.match("([A-Za-z0-9]+) = ?(.*)", line) - if not res: - test_vector.others += [line] - else: - token = res.group(1).lower() - data = res.group(2).lower() - - conversion = conversions.get(token, None) - if conversion is None: - if len(data) % 2 != 0: - data = "0" + data - setattr(test_vector, token, binascii.unhexlify(data)) - else: - setattr(test_vector, token, conversion(data)) - - # This line is ignored - return results - - -def load_test_vectors(dir_comps, file_name, description, conversions): - """Load and parse a test vector file - - This function returns a list of objects, one per group of adjacent - KV lines or for a single line in the form "[.*]". - - For a group of lines, the object has one attribute per line. - """ - - results = None - - try: - if not test_vectors_available: - raise FileNotFoundError(errno.ENOENT, - os.strerror(errno.ENOENT), - file_name) - - description = "%s test (%s)" % (description, file_name) - - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - with open(full_file_name) as file_in: - results = _load_tests(dir_comps, file_in, description, conversions) - - except FileNotFoundError: - warnings.warn("Warning: skipping extended tests for " + description, - UserWarning, - stacklevel=2) - - return results - - -def load_test_vectors_wycheproof(dir_comps, file_name, description, - root_tag={}, group_tag={}, unit_tag={}): - - result = [] - try: - if not test_vectors_available: - raise FileNotFoundError(errno.ENOENT, - os.strerror(errno.ENOENT), - file_name) - - init_dir = os.path.dirname(pycryptodome_test_vectors.__file__) - full_file_name = os.path.join(os.path.join(init_dir, *dir_comps), file_name) - with open(full_file_name) as file_in: - tv_tree = json.load(file_in) - - except FileNotFoundError: - warnings.warn("Warning: skipping extended tests for " + description, - UserWarning, - stacklevel=2) - return result - - class TestVector(object): - pass - - common_root = {} - for k, v in root_tag.items(): - common_root[k] = v(tv_tree) - - for group in tv_tree['testGroups']: - - common_group = {} - for k, v in group_tag.items(): - common_group[k] = v(group) - - for test in group['tests']: - tv = TestVector() - - for k, v in common_root.items(): - setattr(tv, k, v) - for k, v in common_group.items(): - setattr(tv, k, v) - - tv.id = test['tcId'] - tv.comment = test['comment'] - for attr in 'key', 'iv', 'aad', 'msg', 'ct', 'tag', 'label', 'ikm', 'salt', 'info', 'okm', 'sig': - if attr in test: - setattr(tv, attr, unhexlify(test[attr])) - tv.filename = file_name - - for k, v in unit_tag.items(): - setattr(tv, k, v(test)) - - tv.valid = test['result'] != "invalid" - tv.warning = test['result'] == "acceptable" - result.append(tv) - - return result - diff --git a/Crypto/SelfTest/st_common.py b/Crypto/SelfTest/st_common.py deleted file mode 100644 index e098d81..0000000 --- a/Crypto/SelfTest/st_common.py +++ /dev/null @@ -1,55 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SelfTest/st_common.py: Common functions for SelfTest modules -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# 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. -# =================================================================== - -"""Common functions for SelfTest modules""" - -import unittest -import binascii -from Crypto.Util.py3compat import b - - -def list_test_cases(class_): - """Return a list of TestCase instances given a TestCase class - - This is useful when you have defined test* methods on your TestCase class. - """ - return unittest.TestLoader().loadTestsFromTestCase(class_) - -def strip_whitespace(s): - """Remove whitespace from a text or byte string""" - if isinstance(s,str): - return b("".join(s.split())) - else: - return b("").join(s.split()) - -def a2b_hex(s): - """Convert hexadecimal to binary, ignoring whitespace""" - return binascii.a2b_hex(strip_whitespace(s)) - -def b2a_hex(s): - """Convert binary to hexadecimal""" - # For completeness - return binascii.b2a_hex(s) - -# vim:set ts=4 sw=4 sts=4 expandtab: diff --git a/Crypto/Signature/DSS.py b/Crypto/Signature/DSS.py deleted file mode 100644 index 4092d42..0000000 --- a/Crypto/Signature/DSS.py +++ /dev/null @@ -1,416 +0,0 @@ -# -# Signature/DSS.py : DSS.py -# -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -__all__ = ['new'] - - -from Crypto.Util.asn1 import DerSequence -from Crypto.Util.number import long_to_bytes -from Crypto.Math.Numbers import Integer - -from Crypto.Hash import HMAC -from Crypto.PublicKey.ECC import EccKey -from Crypto.PublicKey.DSA import DsaKey - - -class DssSigScheme(object): - """A (EC)DSA signature object. - Do not instantiate directly. - Use :func:`Crypto.Signature.DSS.new`. - """ - - def __init__(self, key, encoding, order): - """Create a new Digital Signature Standard (DSS) object. - - Do not instantiate this object directly, - use `Crypto.Signature.DSS.new` instead. - """ - - self._key = key - self._encoding = encoding - self._order = order - - self._order_bits = self._order.size_in_bits() - self._order_bytes = (self._order_bits - 1) // 8 + 1 - - def can_sign(self): - """Return ``True`` if this signature object can be used - for signing messages.""" - - return self._key.has_private() - - def _compute_nonce(self, msg_hash): - raise NotImplementedError("To be provided by subclasses") - - def _valid_hash(self, msg_hash): - raise NotImplementedError("To be provided by subclasses") - - def sign(self, msg_hash): - """Produce the DSA/ECDSA signature of a message. - - :parameter msg_hash: - The hash that was carried out over the message. - The object belongs to the :mod:`Crypto.Hash` package. - - Under mode *'fips-186-3'*, the hash must be a FIPS - approved secure hash (SHA-1 or a member of the SHA-2 family), - of cryptographic strength appropriate for the DSA key. - For instance, a 3072/256 DSA key can only be used - in combination with SHA-512. - :type msg_hash: hash object - - :return: The signature as a *byte string* - :raise ValueError: if the hash algorithm is incompatible to the (EC)DSA key - :raise TypeError: if the (EC)DSA key has no private half - """ - - if not self._valid_hash(msg_hash): - raise ValueError("Hash is not sufficiently strong") - - # Generate the nonce k (critical!) - nonce = self._compute_nonce(msg_hash) - - # Perform signature using the raw API - z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes]) - sig_pair = self._key._sign(z, nonce) - - # Encode the signature into a single byte string - if self._encoding == 'binary': - output = b"".join([long_to_bytes(x, self._order_bytes) - for x in sig_pair]) - else: - # Dss-sig ::= SEQUENCE { - # r INTEGER, - # s INTEGER - # } - # Ecdsa-Sig-Value ::= SEQUENCE { - # r INTEGER, - # s INTEGER - # } - output = DerSequence(sig_pair).encode() - - return output - - def verify(self, msg_hash, signature): - """Check if a certain (EC)DSA signature is authentic. - - :parameter msg_hash: - The hash that was carried out over the message. - This is an object belonging to the :mod:`Crypto.Hash` module. - - Under mode *'fips-186-3'*, the hash must be a FIPS - approved secure hash (SHA-1 or a member of the SHA-2 family), - of cryptographic strength appropriate for the DSA key. - For instance, a 3072/256 DSA key can only be used in - combination with SHA-512. - :type msg_hash: hash object - - :parameter signature: - The signature that needs to be validated - :type signature: byte string - - :raise ValueError: if the signature is not authentic - """ - - if not self._valid_hash(msg_hash): - raise ValueError("Hash is not sufficiently strong") - - if self._encoding == 'binary': - if len(signature) != (2 * self._order_bytes): - raise ValueError("The signature is not authentic (length)") - r_prime, s_prime = [Integer.from_bytes(x) - for x in (signature[:self._order_bytes], - signature[self._order_bytes:])] - else: - try: - der_seq = DerSequence().decode(signature, strict=True) - except (ValueError, IndexError): - raise ValueError("The signature is not authentic (DER)") - if len(der_seq) != 2 or not der_seq.hasOnlyInts(): - raise ValueError("The signature is not authentic (DER content)") - r_prime, s_prime = Integer(der_seq[0]), Integer(der_seq[1]) - - if not (0 < r_prime < self._order) or not (0 < s_prime < self._order): - raise ValueError("The signature is not authentic (d)") - - z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes]) - result = self._key._verify(z, (r_prime, s_prime)) - if not result: - raise ValueError("The signature is not authentic") - # Make PyCrypto code to fail - return False - - -class DeterministicDsaSigScheme(DssSigScheme): - # Also applicable to ECDSA - - def __init__(self, key, encoding, order, private_key): - super(DeterministicDsaSigScheme, self).__init__(key, encoding, order) - self._private_key = private_key - - def _bits2int(self, bstr): - """See 2.3.2 in RFC6979""" - - result = Integer.from_bytes(bstr) - q_len = self._order.size_in_bits() - b_len = len(bstr) * 8 - if b_len > q_len: - # Only keep leftmost q_len bits - result >>= (b_len - q_len) - return result - - def _int2octets(self, int_mod_q): - """See 2.3.3 in RFC6979""" - - assert 0 < int_mod_q < self._order - return long_to_bytes(int_mod_q, self._order_bytes) - - def _bits2octets(self, bstr): - """See 2.3.4 in RFC6979""" - - z1 = self._bits2int(bstr) - if z1 < self._order: - z2 = z1 - else: - z2 = z1 - self._order - return self._int2octets(z2) - - def _compute_nonce(self, mhash): - """Generate k in a deterministic way""" - - # See section 3.2 in RFC6979.txt - # Step a - h1 = mhash.digest() - # Step b - mask_v = b'\x01' * mhash.digest_size - # Step c - nonce_k = b'\x00' * mhash.digest_size - - for int_oct in (b'\x00', b'\x01'): - # Step d/f - nonce_k = HMAC.new(nonce_k, - mask_v + int_oct + - self._int2octets(self._private_key) + - self._bits2octets(h1), mhash).digest() - # Step e/g - mask_v = HMAC.new(nonce_k, mask_v, mhash).digest() - - nonce = -1 - while not (0 < nonce < self._order): - # Step h.C (second part) - if nonce != -1: - nonce_k = HMAC.new(nonce_k, mask_v + b'\x00', - mhash).digest() - mask_v = HMAC.new(nonce_k, mask_v, mhash).digest() - - # Step h.A - mask_t = b"" - - # Step h.B - while len(mask_t) < self._order_bytes: - mask_v = HMAC.new(nonce_k, mask_v, mhash).digest() - mask_t += mask_v - - # Step h.C (first part) - nonce = self._bits2int(mask_t) - return nonce - - def _valid_hash(self, msg_hash): - return True - - -class FipsDsaSigScheme(DssSigScheme): - - #: List of L (bit length of p) and N (bit length of q) combinations - #: that are allowed by FIPS 186-3. The security level is provided in - #: Table 2 of FIPS 800-57 (rev3). - _fips_186_3_L_N = ( - (1024, 160), # 80 bits (SHA-1 or stronger) - (2048, 224), # 112 bits (SHA-224 or stronger) - (2048, 256), # 128 bits (SHA-256 or stronger) - (3072, 256) # 256 bits (SHA-512) - ) - - def __init__(self, key, encoding, order, randfunc): - super(FipsDsaSigScheme, self).__init__(key, encoding, order) - self._randfunc = randfunc - - L = Integer(key.p).size_in_bits() - if (L, self._order_bits) not in self._fips_186_3_L_N: - error = ("L/N (%d, %d) is not compliant to FIPS 186-3" - % (L, self._order_bits)) - raise ValueError(error) - - def _compute_nonce(self, msg_hash): - # hash is not used - return Integer.random_range(min_inclusive=1, - max_exclusive=self._order, - randfunc=self._randfunc) - - def _valid_hash(self, msg_hash): - """Verify that SHA-1, SHA-2 or SHA-3 are used""" - return (msg_hash.oid == "1.3.14.3.2.26" or - msg_hash.oid.startswith("2.16.840.1.101.3.4.2.")) - - -class FipsEcDsaSigScheme(DssSigScheme): - - def __init__(self, key, encoding, order, randfunc): - super(FipsEcDsaSigScheme, self).__init__(key, encoding, order) - self._randfunc = randfunc - - def _compute_nonce(self, msg_hash): - return Integer.random_range(min_inclusive=1, - max_exclusive=self._key._curve.order, - randfunc=self._randfunc) - - def _valid_hash(self, msg_hash): - """Verify that SHA-[23] (256|384|512) bits are used to - match the security of P-256 (128 bits), P-384 (192 bits) - or P-521 (256 bits)""" - - modulus_bits = self._key.pointQ.size_in_bits() - - sha256 = ( "2.16.840.1.101.3.4.2.1", "2.16.840.1.101.3.4.2.8" ) - sha384 = ( "2.16.840.1.101.3.4.2.2", "2.16.840.1.101.3.4.2.9" ) - sha512 = ( "2.16.840.1.101.3.4.2.3", "2.16.840.1.101.3.4.2.10") - - if msg_hash.oid in sha256: - return modulus_bits <= 256 - elif msg_hash.oid in sha384: - return modulus_bits <= 384 - else: - return msg_hash.oid in sha512 - - -def new(key, mode, encoding='binary', randfunc=None): - """Create a signature object :class:`DSS_SigScheme` that - can perform (EC)DSA signature or verification. - - .. note:: - Refer to `NIST SP 800 Part 1 Rev 4`_ (or newer release) for an - overview of the recommended key lengths. - - :parameter key: - The key to use for computing the signature (*private* keys only) - or verifying one: it must be either - :class:`Crypto.PublicKey.DSA` or :class:`Crypto.PublicKey.ECC`. - - For DSA keys, let ``L`` and ``N`` be the bit lengths of the modulus ``p`` - and of ``q``: the pair ``(L,N)`` must appear in the following list, - in compliance to section 4.2 of `FIPS 186-4`_: - - - (1024, 160) *legacy only; do not create new signatures with this* - - (2048, 224) *deprecated; do not create new signatures with this* - - (2048, 256) - - (3072, 256) - - For ECC, only keys over P-256, P384, and P-521 are accepted. - :type key: - a key object - - :parameter mode: - The parameter can take these values: - - - *'fips-186-3'*. The signature generation is randomized and carried out - according to `FIPS 186-3`_: the nonce ``k`` is taken from the RNG. - - *'deterministic-rfc6979'*. The signature generation is not - randomized. See RFC6979_. - :type mode: - string - - :parameter encoding: - How the signature is encoded. This value determines the output of - :meth:`sign` and the input to :meth:`verify`. - - The following values are accepted: - - - *'binary'* (default), the signature is the raw concatenation - of ``r`` and ``s``. It is defined in the IEEE P.1363 standard. - - For DSA, the size in bytes of the signature is ``N/4`` bytes - (e.g. 64 for ``N=256``). - - For ECDSA, the signature is always twice the length of a point - coordinate (e.g. 64 bytes for P-256). - - - *'der'*, the signature is a ASN.1 DER SEQUENCE - with two INTEGERs (``r`` and ``s``). It is defined in RFC3279_. - The size of the signature is variable. - :type encoding: string - - :parameter randfunc: - A function that returns random *byte strings*, of a given length. - If omitted, the internal RNG is used. - Only applicable for the *'fips-186-3'* mode. - :type randfunc: callable - - .. _FIPS 186-3: http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf - .. _FIPS 186-4: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - .. _NIST SP 800 Part 1 Rev 4: http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r4.pdf - .. _RFC6979: http://tools.ietf.org/html/rfc6979 - .. _RFC3279: https://tools.ietf.org/html/rfc3279#section-2.2.2 - """ - - # The goal of the 'mode' parameter is to avoid to - # have the current version of the standard as default. - # - # Over time, such version will be superseded by (for instance) - # FIPS 186-4 and it will be odd to have -3 as default. - - if encoding not in ('binary', 'der'): - raise ValueError("Unknown encoding '%s'" % encoding) - - if isinstance(key, EccKey): - order = key._curve.order - private_key_attr = 'd' - elif isinstance(key, DsaKey): - order = Integer(key.q) - private_key_attr = 'x' - else: - raise ValueError("Unsupported key type " + str(type(key))) - - if key.has_private(): - private_key = getattr(key, private_key_attr) - else: - private_key = None - - if mode == 'deterministic-rfc6979': - return DeterministicDsaSigScheme(key, encoding, order, private_key) - elif mode == 'fips-186-3': - if isinstance(key, EccKey): - return FipsEcDsaSigScheme(key, encoding, order, randfunc) - else: - return FipsDsaSigScheme(key, encoding, order, randfunc) - else: - raise ValueError("Unknown DSS mode '%s'" % mode) diff --git a/Crypto/Signature/DSS.pyi b/Crypto/Signature/DSS.pyi deleted file mode 100644 index 08cad81..0000000 --- a/Crypto/Signature/DSS.pyi +++ /dev/null @@ -1,27 +0,0 @@ -from typing import Union, Optional, Callable -from typing_extensions import Protocol - -from Crypto.PublicKey.DSA import DsaKey -from Crypto.PublicKey.ECC import EccKey - -class Hash(Protocol): - def digest(self) -> bytes: ... - -__all__ = ['new'] - -class DssSigScheme: - def __init__(self, key: Union[DsaKey, EccKey], encoding: str, order: int) -> None: ... - def can_sign(self) -> bool: ... - def sign(self, msg_hash: Hash) -> bytes: ... - def verify(self, msg_hash: Hash, signature: bytes) -> bool: ... - -class DeterministicDsaSigScheme(DssSigScheme): - def __init__(self, key, encoding, order, private_key) -> None: ... - -class FipsDsaSigScheme(DssSigScheme): - def __init__(self, key: DsaKey, encoding: str, order: int, randfunc: Callable) -> None: ... - -class FipsEcDsaSigScheme(DssSigScheme): - def __init__(self, key: EccKey, encoding: str, order: int, randfunc: Callable) -> None: ... - -def new(key: Union[DsaKey, EccKey], mode: str, encoding: Optional[str]='binary', randfunc: Optional[Callable]=None) -> Union[DeterministicDsaSigScheme, FipsDsaSigScheme, FipsEcDsaSigScheme]: ... diff --git a/Crypto/Signature/PKCS1_PSS.py b/Crypto/Signature/PKCS1_PSS.py deleted file mode 100644 index c39d388..0000000 --- a/Crypto/Signature/PKCS1_PSS.py +++ /dev/null @@ -1,55 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -""" -Legacy module for PKCS#1 PSS signatures. - -:undocumented: __package__ -""" - -import types - -from Crypto.Signature import pss - - -def _pycrypto_verify(self, hash_object, signature): - try: - self._verify(hash_object, signature) - except (ValueError, TypeError): - return False - return True - - -def new(rsa_key, mgfunc=None, saltLen=None, randfunc=None): - pkcs1 = pss.new(rsa_key, mask_func=mgfunc, - salt_bytes=saltLen, rand_func=randfunc) - pkcs1._verify = pkcs1.verify - pkcs1.verify = types.MethodType(_pycrypto_verify, pkcs1) - return pkcs1 diff --git a/Crypto/Signature/PKCS1_PSS.pyi b/Crypto/Signature/PKCS1_PSS.pyi deleted file mode 100644 index 882cc8f..0000000 --- a/Crypto/Signature/PKCS1_PSS.pyi +++ /dev/null @@ -1,7 +0,0 @@ -from typing import Optional, Callable - -from Crypto.PublicKey.RSA import RsaKey -from Crypto.Signature.pss import PSS_SigScheme - - -def new(rsa_key: RsaKey, mgfunc: Optional[Callable]=None, saltLen: Optional[int]=None, randfunc: Optional[Callable]=None) -> PSS_SigScheme: ... diff --git a/Crypto/Signature/PKCS1_v1_5.py b/Crypto/Signature/PKCS1_v1_5.py deleted file mode 100644 index ac888ed..0000000 --- a/Crypto/Signature/PKCS1_v1_5.py +++ /dev/null @@ -1,53 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -""" -Legacy module for PKCS#1 v1.5 signatures. - -:undocumented: __package__ -""" - -import types - -from Crypto.Signature import pkcs1_15 - -def _pycrypto_verify(self, hash_object, signature): - try: - self._verify(hash_object, signature) - except (ValueError, TypeError): - return False - return True - -def new(rsa_key): - pkcs1 = pkcs1_15.new(rsa_key) - pkcs1._verify = pkcs1.verify - pkcs1.verify = types.MethodType(_pycrypto_verify, pkcs1) - return pkcs1 - diff --git a/Crypto/Signature/PKCS1_v1_5.pyi b/Crypto/Signature/PKCS1_v1_5.pyi deleted file mode 100644 index 55b9637..0000000 --- a/Crypto/Signature/PKCS1_v1_5.pyi +++ /dev/null @@ -1,6 +0,0 @@ -from Crypto.PublicKey.RSA import RsaKey - -from Crypto.Signature.pkcs1_15 import PKCS115_SigScheme - - -def new(rsa_key: RsaKey) -> PKCS115_SigScheme: ... \ No newline at end of file diff --git a/Crypto/Signature/__init__.py b/Crypto/Signature/__init__.py deleted file mode 100644 index da028a5..0000000 --- a/Crypto/Signature/__init__.py +++ /dev/null @@ -1,36 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -"""Digital signature protocols - -A collection of standardized protocols to carry out digital signatures. -""" - -__all__ = ['PKCS1_v1_5', 'PKCS1_PSS', 'DSS', 'pkcs1_15', 'pss'] diff --git a/Crypto/Signature/pkcs1_15.py b/Crypto/Signature/pkcs1_15.py deleted file mode 100644 index 54a4bf7..0000000 --- a/Crypto/Signature/pkcs1_15.py +++ /dev/null @@ -1,222 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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 Crypto.Util.number -from Crypto.Util.number import ceil_div, bytes_to_long, long_to_bytes -from Crypto.Util.asn1 import DerSequence, DerNull, DerOctetString, DerObjectId - -class PKCS115_SigScheme: - """A signature object for ``RSASSA-PKCS1-v1_5``. - Do not instantiate directly. - Use :func:`Crypto.Signature.pkcs1_15.new`. - """ - - def __init__(self, rsa_key): - """Initialize this PKCS#1 v1.5 signature scheme object. - - :Parameters: - rsa_key : an RSA key object - Creation of signatures is only possible if this is a *private* - RSA key. Verification of signatures is always possible. - """ - self._key = rsa_key - - def can_sign(self): - """Return ``True`` if this object can be used to sign messages.""" - return self._key.has_private() - - def sign(self, msg_hash): - """Create the PKCS#1 v1.5 signature of a message. - - This function is also called ``RSASSA-PKCS1-V1_5-SIGN`` and - it is specified in - `section 8.2.1 of RFC8017 `_. - - :parameter msg_hash: - This is an object from the :mod:`Crypto.Hash` package. - It has been used to digest the message to sign. - :type msg_hash: hash object - - :return: the signature encoded as a *byte string*. - :raise ValueError: if the RSA key is not long enough for the given hash algorithm. - :raise TypeError: if the RSA key has no private half. - """ - - # See 8.2.1 in RFC3447 - modBits = Crypto.Util.number.size(self._key.n) - k = ceil_div(modBits,8) # Convert from bits to bytes - - # Step 1 - em = _EMSA_PKCS1_V1_5_ENCODE(msg_hash, k) - # Step 2a (OS2IP) - em_int = bytes_to_long(em) - # Step 2b (RSASP1) - m_int = self._key._decrypt(em_int) - # Step 2c (I2OSP) - signature = long_to_bytes(m_int, k) - return signature - - def verify(self, msg_hash, signature): - """Check if the PKCS#1 v1.5 signature over a message is valid. - - This function is also called ``RSASSA-PKCS1-V1_5-VERIFY`` and - it is specified in - `section 8.2.2 of RFC8037 `_. - - :parameter msg_hash: - The hash that was carried out over the message. This is an object - belonging to the :mod:`Crypto.Hash` module. - :type parameter: hash object - - :parameter signature: - The signature that needs to be validated. - :type signature: byte string - - :raise ValueError: if the signature is not valid. - """ - - # See 8.2.2 in RFC3447 - modBits = Crypto.Util.number.size(self._key.n) - k = ceil_div(modBits, 8) # Convert from bits to bytes - - # Step 1 - if len(signature) != k: - raise ValueError("Invalid signature") - # Step 2a (O2SIP) - signature_int = bytes_to_long(signature) - # Step 2b (RSAVP1) - em_int = self._key._encrypt(signature_int) - # Step 2c (I2OSP) - em1 = long_to_bytes(em_int, k) - # Step 3 - try: - possible_em1 = [ _EMSA_PKCS1_V1_5_ENCODE(msg_hash, k, True) ] - # MD2/4/5 hashes always require NULL params in AlgorithmIdentifier. - # For all others, it is optional. - try: - algorithm_is_md = msg_hash.oid.startswith('1.2.840.113549.2.') - except AttributeError: - algorithm_is_md = False - if not algorithm_is_md: # MD2/MD4/MD5 - possible_em1.append(_EMSA_PKCS1_V1_5_ENCODE(msg_hash, k, False)) - except ValueError: - raise ValueError("Invalid signature") - # Step 4 - # By comparing the full encodings (as opposed to checking each - # of its components one at a time) we avoid attacks to the padding - # scheme like Bleichenbacher's (see http://www.mail-archive.com/cryptography@metzdowd.com/msg06537). - # - if em1 not in possible_em1: - raise ValueError("Invalid signature") - pass - - -def _EMSA_PKCS1_V1_5_ENCODE(msg_hash, emLen, with_hash_parameters=True): - """ - Implement the ``EMSA-PKCS1-V1_5-ENCODE`` function, as defined - in PKCS#1 v2.1 (RFC3447, 9.2). - - ``_EMSA-PKCS1-V1_5-ENCODE`` actually accepts the message ``M`` as input, - and hash it internally. Here, we expect that the message has already - been hashed instead. - - :Parameters: - msg_hash : hash object - The hash object that holds the digest of the message being signed. - emLen : int - The length the final encoding must have, in bytes. - with_hash_parameters : bool - If True (default), include NULL parameters for the hash - algorithm in the ``digestAlgorithm`` SEQUENCE. - - :attention: the early standard (RFC2313) stated that ``DigestInfo`` - had to be BER-encoded. This means that old signatures - might have length tags in indefinite form, which - is not supported in DER. Such encoding cannot be - reproduced by this function. - - :Return: An ``emLen`` byte long string that encodes the hash. - """ - - # First, build the ASN.1 DER object DigestInfo: - # - # DigestInfo ::= SEQUENCE { - # digestAlgorithm AlgorithmIdentifier, - # digest OCTET STRING - # } - # - # where digestAlgorithm identifies the hash function and shall be an - # algorithm ID with an OID in the set PKCS1-v1-5DigestAlgorithms. - # - # PKCS1-v1-5DigestAlgorithms ALGORITHM-IDENTIFIER ::= { - # { OID id-md2 PARAMETERS NULL }| - # { OID id-md5 PARAMETERS NULL }| - # { OID id-sha1 PARAMETERS NULL }| - # { OID id-sha256 PARAMETERS NULL }| - # { OID id-sha384 PARAMETERS NULL }| - # { OID id-sha512 PARAMETERS NULL } - # } - # - # Appendix B.1 also says that for SHA-1/-2 algorithms, the parameters - # should be omitted. They may be present, but when they are, they shall - # have NULL value. - - digestAlgo = DerSequence([ DerObjectId(msg_hash.oid).encode() ]) - - if with_hash_parameters: - digestAlgo.append(DerNull().encode()) - - digest = DerOctetString(msg_hash.digest()) - digestInfo = DerSequence([ - digestAlgo.encode(), - digest.encode() - ]).encode() - - # We need at least 11 bytes for the remaining data: 3 fixed bytes and - # at least 8 bytes of padding). - if emLen bytes: ... - -class PKCS115_SigScheme: - def __init__(self, rsa_key: RsaKey) -> None: ... - def can_sign(self) -> bool: ... - def sign(self, msg_hash: Hash) -> bytes: ... - def verify(self, msg_hash: Hash, signature: bytes) -> None: ... - -def _EMSA_PKCS1_V1_5_ENCODE(msg_hash: Hash, emLen: int, with_hash_parameters: Optional[bool]=True) -> bytes: ... - -def new(rsa_key: RsaKey) -> PKCS115_SigScheme: ... diff --git a/Crypto/Signature/pss.py b/Crypto/Signature/pss.py deleted file mode 100644 index 5f34ace..0000000 --- a/Crypto/Signature/pss.py +++ /dev/null @@ -1,386 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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 Crypto.Util.py3compat import bchr, bord, iter_range -import Crypto.Util.number -from Crypto.Util.number import (ceil_div, - long_to_bytes, - bytes_to_long - ) -from Crypto.Util.strxor import strxor -from Crypto import Random - - -class PSS_SigScheme: - """A signature object for ``RSASSA-PSS``. - Do not instantiate directly. - Use :func:`Crypto.Signature.pss.new`. - """ - - def __init__(self, key, mgfunc, saltLen, randfunc): - """Initialize this PKCS#1 PSS signature scheme object. - - :Parameters: - key : an RSA key object - If a private half is given, both signature and - verification are possible. - If a public half is given, only verification is possible. - mgfunc : callable - A mask generation function that accepts two parameters: - a string to use as seed, and the lenth of the mask to - generate, in bytes. - saltLen : integer - Length of the salt, in bytes. - randfunc : callable - A function that returns random bytes. - """ - - self._key = key - self._saltLen = saltLen - self._mgfunc = mgfunc - self._randfunc = randfunc - - def can_sign(self): - """Return ``True`` if this object can be used to sign messages.""" - return self._key.has_private() - - def sign(self, msg_hash): - """Create the PKCS#1 PSS signature of a message. - - This function is also called ``RSASSA-PSS-SIGN`` and - it is specified in - `section 8.1.1 of RFC8017 `_. - - :parameter msg_hash: - This is an object from the :mod:`Crypto.Hash` package. - It has been used to digest the message to sign. - :type msg_hash: hash object - - :return: the signature encoded as a *byte string*. - :raise ValueError: if the RSA key is not long enough for the given hash algorithm. - :raise TypeError: if the RSA key has no private half. - """ - - # Set defaults for salt length and mask generation function - if self._saltLen is None: - sLen = msg_hash.digest_size - else: - sLen = self._saltLen - - if self._mgfunc is None: - mgf = lambda x, y: MGF1(x, y, msg_hash) - else: - mgf = self._mgfunc - - modBits = Crypto.Util.number.size(self._key.n) - - # See 8.1.1 in RFC3447 - k = ceil_div(modBits, 8) # k is length in bytes of the modulus - # Step 1 - em = _EMSA_PSS_ENCODE(msg_hash, modBits-1, self._randfunc, mgf, sLen) - # Step 2a (OS2IP) - em_int = bytes_to_long(em) - # Step 2b (RSASP1) - m_int = self._key._decrypt(em_int) - # Step 2c (I2OSP) - signature = long_to_bytes(m_int, k) - return signature - - def verify(self, msg_hash, signature): - """Check if the PKCS#1 PSS signature over a message is valid. - - This function is also called ``RSASSA-PSS-VERIFY`` and - it is specified in - `section 8.1.2 of RFC8037 `_. - - :parameter msg_hash: - The hash that was carried out over the message. This is an object - belonging to the :mod:`Crypto.Hash` module. - :type parameter: hash object - - :parameter signature: - The signature that needs to be validated. - :type signature: bytes - - :raise ValueError: if the signature is not valid. - """ - - # Set defaults for salt length and mask generation function - if self._saltLen is None: - sLen = msg_hash.digest_size - else: - sLen = self._saltLen - if self._mgfunc: - mgf = self._mgfunc - else: - mgf = lambda x, y: MGF1(x, y, msg_hash) - - modBits = Crypto.Util.number.size(self._key.n) - - # See 8.1.2 in RFC3447 - k = ceil_div(modBits, 8) # Convert from bits to bytes - # Step 1 - if len(signature) != k: - raise ValueError("Incorrect signature") - # Step 2a (O2SIP) - signature_int = bytes_to_long(signature) - # Step 2b (RSAVP1) - em_int = self._key._encrypt(signature_int) - # Step 2c (I2OSP) - emLen = ceil_div(modBits - 1, 8) - em = long_to_bytes(em_int, emLen) - # Step 3/4 - _EMSA_PSS_VERIFY(msg_hash, em, modBits-1, mgf, sLen) - - -def MGF1(mgfSeed, maskLen, hash_gen): - """Mask Generation Function, described in `B.2.1 of RFC8017 - `_. - - :param mfgSeed: - seed from which the mask is generated - :type mfgSeed: byte string - - :param maskLen: - intended length in bytes of the mask - :type maskLen: integer - - :param hash_gen: - A module or a hash object from :mod:`Crypto.Hash` - :type hash_object: - - :return: the mask, as a *byte string* - """ - - T = b"" - for counter in iter_range(ceil_div(maskLen, hash_gen.digest_size)): - c = long_to_bytes(counter, 4) - hobj = hash_gen.new() - hobj.update(mgfSeed + c) - T = T + hobj.digest() - assert(len(T) >= maskLen) - return T[:maskLen] - - -def _EMSA_PSS_ENCODE(mhash, emBits, randFunc, mgf, sLen): - r""" - Implement the ``EMSA-PSS-ENCODE`` function, as defined - in PKCS#1 v2.1 (RFC3447, 9.1.1). - - The original ``EMSA-PSS-ENCODE`` actually accepts the message ``M`` - as input, and hash it internally. Here, we expect that the message - has already been hashed instead. - - :Parameters: - mhash : hash object - The hash object that holds the digest of the message being signed. - emBits : int - Maximum length of the final encoding, in bits. - randFunc : callable - An RNG function that accepts as only parameter an int, and returns - a string of random bytes, to be used as salt. - mgf : callable - A mask generation function that accepts two parameters: a string to - use as seed, and the lenth of the mask to generate, in bytes. - sLen : int - Length of the salt, in bytes. - - :Return: An ``emLen`` byte long string that encodes the hash - (with ``emLen = \ceil(emBits/8)``). - - :Raise ValueError: - When digest or salt length are too big. - """ - - emLen = ceil_div(emBits, 8) - - # Bitmask of digits that fill up - lmask = 0 - for i in iter_range(8*emLen-emBits): - lmask = lmask >> 1 | 0x80 - - # Step 1 and 2 have been already done - # Step 3 - if emLen < mhash.digest_size+sLen+2: - raise ValueError("Digest or salt length are too long" - " for given key size.") - # Step 4 - salt = randFunc(sLen) - # Step 5 - m_prime = bchr(0)*8 + mhash.digest() + salt - # Step 6 - h = mhash.new() - h.update(m_prime) - # Step 7 - ps = bchr(0)*(emLen-sLen-mhash.digest_size-2) - # Step 8 - db = ps + bchr(1) + salt - # Step 9 - dbMask = mgf(h.digest(), emLen-mhash.digest_size-1) - # Step 10 - maskedDB = strxor(db, dbMask) - # Step 11 - maskedDB = bchr(bord(maskedDB[0]) & ~lmask) + maskedDB[1:] - # Step 12 - em = maskedDB + h.digest() + bchr(0xBC) - return em - - -def _EMSA_PSS_VERIFY(mhash, em, emBits, mgf, sLen): - """ - Implement the ``EMSA-PSS-VERIFY`` function, as defined - in PKCS#1 v2.1 (RFC3447, 9.1.2). - - ``EMSA-PSS-VERIFY`` actually accepts the message ``M`` as input, - and hash it internally. Here, we expect that the message has already - been hashed instead. - - :Parameters: - mhash : hash object - The hash object that holds the digest of the message to be verified. - em : string - The signature to verify, therefore proving that the sender really - signed the message that was received. - emBits : int - Length of the final encoding (em), in bits. - mgf : callable - A mask generation function that accepts two parameters: a string to - use as seed, and the lenth of the mask to generate, in bytes. - sLen : int - Length of the salt, in bytes. - - :Raise ValueError: - When the encoding is inconsistent, or the digest or salt lengths - are too big. - """ - - emLen = ceil_div(emBits, 8) - - # Bitmask of digits that fill up - lmask = 0 - for i in iter_range(8*emLen-emBits): - lmask = lmask >> 1 | 0x80 - - # Step 1 and 2 have been already done - # Step 3 - if emLen < mhash.digest_size+sLen+2: - raise ValueError("Incorrect signature") - # Step 4 - if ord(em[-1:]) != 0xBC: - raise ValueError("Incorrect signature") - # Step 5 - maskedDB = em[:emLen-mhash.digest_size-1] - h = em[emLen-mhash.digest_size-1:-1] - # Step 6 - if lmask & bord(em[0]): - raise ValueError("Incorrect signature") - # Step 7 - dbMask = mgf(h, emLen-mhash.digest_size-1) - # Step 8 - db = strxor(maskedDB, dbMask) - # Step 9 - db = bchr(bord(db[0]) & ~lmask) + db[1:] - # Step 10 - if not db.startswith(bchr(0)*(emLen-mhash.digest_size-sLen-2) + bchr(1)): - raise ValueError("Incorrect signature") - # Step 11 - if sLen > 0: - salt = db[-sLen:] - else: - salt = b"" - # Step 12 - m_prime = bchr(0)*8 + mhash.digest() + salt - # Step 13 - hobj = mhash.new() - hobj.update(m_prime) - hp = hobj.digest() - # Step 14 - if h != hp: - raise ValueError("Incorrect signature") - - -def new(rsa_key, **kwargs): - """Create an object for making or verifying PKCS#1 PSS signatures. - - :parameter rsa_key: - The RSA key to use for signing or verifying the message. - This is a :class:`Crypto.PublicKey.RSA` object. - Signing is only possible when ``rsa_key`` is a **private** RSA key. - :type rsa_key: RSA object - - :Keyword Arguments: - - * *mask_func* (``callable``) -- - A function that returns the mask (as `bytes`). - It must accept two parameters: a seed (as `bytes`) - and the length of the data to return. - - If not specified, it will be the function :func:`MGF1` defined in - `RFC8017 `_ and - combined with the same hash algorithm applied to the - message to sign or verify. - - If you want to use a different function, for instance still :func:`MGF1` - but together with another hash, you can do:: - - from Crypto.Hash import SHA256 - from Crypto.Signature.pss import MGF1 - mgf = lambda x, y: MGF1(x, y, SHA256) - - * *salt_bytes* (``integer``) -- - Length of the salt, in bytes. - It is a value between 0 and ``emLen - hLen - 2``, where ``emLen`` - is the size of the RSA modulus and ``hLen`` is the size of the digest - applied to the message to sign or verify. - - The salt is generated internally, you don't need to provide it. - - If not specified, the salt length will be ``hLen``. - If it is zero, the signature scheme becomes deterministic. - - Note that in some implementations such as OpenSSL the default - salt length is ``emLen - hLen - 2`` (even though it is not more - secure than ``hLen``). - - * *rand_func* (``callable``) -- - A function that returns random ``bytes``, of the desired length. - The default is :func:`Crypto.Random.get_random_bytes`. - - :return: a :class:`PSS_SigScheme` signature object - """ - - mask_func = kwargs.pop("mask_func", None) - salt_len = kwargs.pop("salt_bytes", None) - rand_func = kwargs.pop("rand_func", None) - if rand_func is None: - rand_func = Random.get_random_bytes - if kwargs: - raise ValueError("Unknown keywords: " + str(kwargs.keys())) - return PSS_SigScheme(rsa_key, mask_func, salt_len, rand_func) diff --git a/Crypto/Signature/pss.pyi b/Crypto/Signature/pss.pyi deleted file mode 100644 index 4d216ca..0000000 --- a/Crypto/Signature/pss.pyi +++ /dev/null @@ -1,30 +0,0 @@ -from typing import Union, Callable, Optional -from typing_extensions import Protocol - -from Crypto.PublicKey.RSA import RsaKey - - -class Hash(Protocol): - def digest(self) -> bytes: ... - def update(self, bytes) -> None: ... - - -class HashModule(Protocol): - @staticmethod - def new(data: Optional[bytes]) -> Hash: ... - - -MaskFunction = Callable[[bytes, int, Union[Hash, HashModule]], bytes] -RndFunction = Callable[[int], bytes] - -class PSS_SigScheme: - def __init__(self, key: RsaKey, mgfunc: RndFunction, saltLen: int, randfunc: RndFunction) -> None: ... - def can_sign(self) -> bool: ... - def sign(self, msg_hash: Hash) -> bytes: ... - def verify(self, msg_hash: Hash, signature: bytes) -> None: ... - - -MGF1 : MaskFunction -def _EMSA_PSS_ENCODE(mhash: Hash, emBits: int, randFunc: RndFunction, mgf:MaskFunction, sLen: int) -> str: ... -def _EMSA_PSS_VERIFY(mhash: Hash, em: str, emBits: int, mgf: MaskFunction, sLen: int) -> None: ... -def new(rsa_key: RsaKey, **kwargs: Union[MaskFunction, RndFunction, int]) -> PSS_SigScheme: ... diff --git a/Crypto/Util/Counter.py b/Crypto/Util/Counter.py deleted file mode 100644 index c67bc95..0000000 --- a/Crypto/Util/Counter.py +++ /dev/null @@ -1,77 +0,0 @@ -# -*- coding: ascii -*- -# -# Util/Counter.py : Fast counter for use with CTR-mode ciphers -# -# Written in 2008 by Dwayne C. Litzenberger -# -# =================================================================== -# 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. -# =================================================================== - -def new(nbits, prefix=b"", suffix=b"", initial_value=1, little_endian=False, allow_wraparound=False): - """Create a stateful counter block function suitable for CTR encryption modes. - - Each call to the function returns the next counter block. - Each counter block is made up by three parts: - - +------+--------------+-------+ - |prefix| counter value|postfix| - +------+--------------+-------+ - - The counter value is incremented by 1 at each call. - - Args: - nbits (integer): - Length of the desired counter value, in bits. It must be a multiple of 8. - prefix (byte string): - The constant prefix of the counter block. By default, no prefix is - used. - suffix (byte string): - The constant postfix of the counter block. By default, no suffix is - used. - initial_value (integer): - The initial value of the counter. Default value is 1. - Its length in bits must not exceed the argument ``nbits``. - little_endian (boolean): - If ``True``, the counter number will be encoded in little endian format. - If ``False`` (default), in big endian format. - allow_wraparound (boolean): - This parameter is ignored. - Returns: - An object that can be passed with the :data:`counter` parameter to a CTR mode - cipher. - - It must hold that *len(prefix) + nbits//8 + len(suffix)* matches the - block size of the underlying block cipher. - """ - - if (nbits % 8) != 0: - raise ValueError("'nbits' must be a multiple of 8") - - iv_bl = initial_value.bit_length() - if iv_bl > nbits: - raise ValueError("Initial value takes %d bits but it is longer than " - "the counter (%d bits)" % - (iv_bl, nbits)) - - # Ignore wraparound - return {"counter_len": nbits // 8, - "prefix": prefix, - "suffix": suffix, - "initial_value": initial_value, - "little_endian": little_endian - } diff --git a/Crypto/Util/Counter.pyi b/Crypto/Util/Counter.pyi deleted file mode 100644 index fa2ffdd..0000000 --- a/Crypto/Util/Counter.pyi +++ /dev/null @@ -1,5 +0,0 @@ -from typing import Optional, Union, Dict - -def new(nbits: int, prefix: Optional[bytes]=..., suffix: Optional[bytes]=..., initial_value: Optional[int]=1, - little_endian: Optional[bool]=False, allow_wraparound: Optional[bool]=False) -> \ - Dict[str, Union[int, bytes, bool]]: ... diff --git a/Crypto/Util/Padding.py b/Crypto/Util/Padding.py deleted file mode 100644 index da69e55..0000000 --- a/Crypto/Util/Padding.py +++ /dev/null @@ -1,108 +0,0 @@ -# -# Util/Padding.py : Functions to manage padding -# -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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. -# =================================================================== - -__all__ = [ 'pad', 'unpad' ] - -from Crypto.Util.py3compat import * - - -def pad(data_to_pad, block_size, style='pkcs7'): - """Apply standard padding. - - Args: - data_to_pad (byte string): - The data that needs to be padded. - block_size (integer): - The block boundary to use for padding. The output length is guaranteed - to be a multiple of :data:`block_size`. - style (string): - Padding algorithm. It can be *'pkcs7'* (default), *'iso7816'* or *'x923'*. - - Return: - byte string : the original data with the appropriate padding added at the end. - """ - - padding_len = block_size-len(data_to_pad)%block_size - if style == 'pkcs7': - padding = bchr(padding_len)*padding_len - elif style == 'x923': - padding = bchr(0)*(padding_len-1) + bchr(padding_len) - elif style == 'iso7816': - padding = bchr(128) + bchr(0)*(padding_len-1) - else: - raise ValueError("Unknown padding style") - return data_to_pad + padding - - -def unpad(padded_data, block_size, style='pkcs7'): - """Remove standard padding. - - Args: - padded_data (byte string): - A piece of data with padding that needs to be stripped. - block_size (integer): - The block boundary to use for padding. The input length - must be a multiple of :data:`block_size`. - style (string): - Padding algorithm. It can be *'pkcs7'* (default), *'iso7816'* or *'x923'*. - Return: - byte string : data without padding. - Raises: - ValueError: if the padding is incorrect. - """ - - pdata_len = len(padded_data) - if pdata_len == 0: - raise ValueError("Zero-length input cannot be unpadded") - if pdata_len % block_size: - raise ValueError("Input data is not padded") - if style in ('pkcs7', 'x923'): - padding_len = bord(padded_data[-1]) - if padding_len<1 or padding_len>min(block_size, pdata_len): - raise ValueError("Padding is incorrect.") - if style == 'pkcs7': - if padded_data[-padding_len:]!=bchr(padding_len)*padding_len: - raise ValueError("PKCS#7 padding is incorrect.") - else: - if padded_data[-padding_len:-1]!=bchr(0)*(padding_len-1): - raise ValueError("ANSI X.923 padding is incorrect.") - elif style == 'iso7816': - padding_len = pdata_len - padded_data.rfind(bchr(128)) - if padding_len<1 or padding_len>min(block_size, pdata_len): - raise ValueError("Padding is incorrect.") - if padding_len>1 and padded_data[1-padding_len:]!=bchr(0)*(padding_len-1): - raise ValueError("ISO 7816-4 padding is incorrect.") - else: - raise ValueError("Unknown padding style") - return padded_data[:-padding_len] - diff --git a/Crypto/Util/Padding.pyi b/Crypto/Util/Padding.pyi deleted file mode 100644 index 4d8d30d..0000000 --- a/Crypto/Util/Padding.pyi +++ /dev/null @@ -1,6 +0,0 @@ -from typing import Optional - -__all__ = [ 'pad', 'unpad' ] - -def pad(data_to_pad: bytes, block_size: int, style: Optional[str]='pkcs7') -> bytes: ... -def unpad(padded_data: bytes, block_size: int, style: Optional[str]='pkcs7') -> bytes: ... \ No newline at end of file diff --git a/Crypto/Util/RFC1751.py b/Crypto/Util/RFC1751.py deleted file mode 100644 index 9ed52d2..0000000 --- a/Crypto/Util/RFC1751.py +++ /dev/null @@ -1,386 +0,0 @@ -# rfc1751.py : Converts between 128-bit strings and a human-readable -# sequence of words, as defined in RFC1751: "A Convention for -# Human-Readable 128-bit Keys", by Daniel L. McDonald. -# -# Part of the Python Cryptography Toolkit -# -# Written by Andrew M. Kuchling and others -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -from __future__ import print_function - -import binascii - -from Crypto.Util.py3compat import bord, bchr - -binary = {0: '0000', 1: '0001', 2: '0010', 3: '0011', 4: '0100', 5: '0101', - 6: '0110', 7: '0111', 8: '1000', 9: '1001', 10: '1010', 11: '1011', - 12: '1100', 13: '1101', 14: '1110', 15: '1111'} - - -def _key2bin(s): - "Convert a key into a string of binary digits" - kl = map(lambda x: bord(x), s) - kl = map(lambda x: binary[x >> 4] + binary[x & 15], kl) - return ''.join(kl) - - -def _extract(key, start, length): - """Extract a bitstring(2.x)/bytestring(2.x) from a string of binary digits, and return its - numeric value.""" - - result = 0 - for y in key[start:start+length]: - result = result * 2 + ord(y) - 48 - return result - - -def key_to_english(key): - """Transform an arbitrary key into a string containing English words. - - Example:: - - >>> from Crypto.Util.RFC1751 import key_to_english - >>> key_to_english(b'66666666') - 'RAM LOIS GOAD CREW CARE HIT' - - Args: - key (byte string): - The key to convert. Its length must be a multiple of 8. - Return: - A string of English words. - """ - - if len(key) % 8 != 0: - raise ValueError('The length of the key must be a multiple of 8.') - - english = '' - for index in range(0, len(key), 8): # Loop over 8-byte subkeys - subkey = key[index:index + 8] - # Compute the parity of the key - skbin = _key2bin(subkey) - p = 0 - for i in range(0, 64, 2): - p = p + _extract(skbin, i, 2) - # Append parity bits to the subkey - skbin = _key2bin(subkey + bchr((p << 6) & 255)) - for i in range(0, 64, 11): - english = english + wordlist[_extract(skbin, i, 11)] + ' ' - - return english.strip() - - -def english_to_key(s): - """Transform a string into a corresponding key. - - Example:: - - >>> from Crypto.Util.RFC1751 import english_to_key - >>> english_to_key('RAM LOIS GOAD CREW CARE HIT') - b'66666666' - - Args: - s (string): the string with the words separated by whitespace; - the number of words must be a multiple of 6. - Return: - A byte string. - """ - - L = s.upper().split() - key = b'' - for index in range(0, len(L), 6): - sublist = L[index:index + 6] - char = 9 * [0] - bits = 0 - for i in sublist: - index = wordlist.index(i) - shift = (8 - (bits + 11) % 8) % 8 - y = index << shift - cl, cc, cr = (y >> 16), (y >> 8) & 0xff, y & 0xff - if (shift > 5): - char[bits >> 3] = char[bits >> 3] | cl - char[(bits >> 3) + 1] = char[(bits >> 3) + 1] | cc - char[(bits >> 3) + 2] = char[(bits >> 3) + 2] | cr - elif shift > -3: - char[bits >> 3] = char[bits >> 3] | cc - char[(bits >> 3) + 1] = char[(bits >> 3) + 1] | cr - else: - char[bits >> 3] = char[bits >> 3] | cr - bits = bits + 11 - - subkey = b'' - for y in char: - subkey = subkey + bchr(y) - - # Check the parity of the resulting key - skbin = _key2bin(subkey) - p = 0 - for i in range(0, 64, 2): - p = p + _extract(skbin, i, 2) - if (p & 3) != _extract(skbin, 64, 2): - raise ValueError("Parity error in resulting key") - key = key + subkey[0:8] - return key - - -wordlist = [ - "A", "ABE", "ACE", "ACT", "AD", "ADA", "ADD", - "AGO", "AID", "AIM", "AIR", "ALL", "ALP", "AM", "AMY", "AN", "ANA", - "AND", "ANN", "ANT", "ANY", "APE", "APS", "APT", "ARC", "ARE", "ARK", - "ARM", "ART", "AS", "ASH", "ASK", "AT", "ATE", "AUG", "AUK", "AVE", - "AWE", "AWK", "AWL", "AWN", "AX", "AYE", "BAD", "BAG", "BAH", "BAM", - "BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", "BEN", "BET", - "BEY", "BIB", "BID", "BIG", "BIN", "BIT", "BOB", "BOG", "BON", "BOO", - "BOP", "BOW", "BOY", "BUB", "BUD", "BUG", "BUM", "BUN", "BUS", "BUT", - "BUY", "BY", "BYE", "CAB", "CAL", "CAM", "CAN", "CAP", "CAR", "CAT", - "CAW", "COD", "COG", "COL", "CON", "COO", "COP", "COT", "COW", "COY", - "CRY", "CUB", "CUE", "CUP", "CUR", "CUT", "DAB", "DAD", "DAM", "DAN", - "DAR", "DAY", "DEE", "DEL", "DEN", "DES", "DEW", "DID", "DIE", "DIG", - "DIN", "DIP", "DO", "DOE", "DOG", "DON", "DOT", "DOW", "DRY", "DUB", - "DUD", "DUE", "DUG", "DUN", "EAR", "EAT", "ED", "EEL", "EGG", "EGO", - "ELI", "ELK", "ELM", "ELY", "EM", "END", "EST", "ETC", "EVA", "EVE", - "EWE", "EYE", "FAD", "FAN", "FAR", "FAT", "FAY", "FED", "FEE", "FEW", - "FIB", "FIG", "FIN", "FIR", "FIT", "FLO", "FLY", "FOE", "FOG", "FOR", - "FRY", "FUM", "FUN", "FUR", "GAB", "GAD", "GAG", "GAL", "GAM", "GAP", - "GAS", "GAY", "GEE", "GEL", "GEM", "GET", "GIG", "GIL", "GIN", "GO", - "GOT", "GUM", "GUN", "GUS", "GUT", "GUY", "GYM", "GYP", "HA", "HAD", - "HAL", "HAM", "HAN", "HAP", "HAS", "HAT", "HAW", "HAY", "HE", "HEM", - "HEN", "HER", "HEW", "HEY", "HI", "HID", "HIM", "HIP", "HIS", "HIT", - "HO", "HOB", "HOC", "HOE", "HOG", "HOP", "HOT", "HOW", "HUB", "HUE", - "HUG", "HUH", "HUM", "HUT", "I", "ICY", "IDA", "IF", "IKE", "ILL", - "INK", "INN", "IO", "ION", "IQ", "IRA", "IRE", "IRK", "IS", "IT", - "ITS", "IVY", "JAB", "JAG", "JAM", "JAN", "JAR", "JAW", "JAY", "JET", - "JIG", "JIM", "JO", "JOB", "JOE", "JOG", "JOT", "JOY", "JUG", "JUT", - "KAY", "KEG", "KEN", "KEY", "KID", "KIM", "KIN", "KIT", "LA", "LAB", - "LAC", "LAD", "LAG", "LAM", "LAP", "LAW", "LAY", "LEA", "LED", "LEE", - "LEG", "LEN", "LEO", "LET", "LEW", "LID", "LIE", "LIN", "LIP", "LIT", - "LO", "LOB", "LOG", "LOP", "LOS", "LOT", "LOU", "LOW", "LOY", "LUG", - "LYE", "MA", "MAC", "MAD", "MAE", "MAN", "MAO", "MAP", "MAT", "MAW", - "MAY", "ME", "MEG", "MEL", "MEN", "MET", "MEW", "MID", "MIN", "MIT", - "MOB", "MOD", "MOE", "MOO", "MOP", "MOS", "MOT", "MOW", "MUD", "MUG", - "MUM", "MY", "NAB", "NAG", "NAN", "NAP", "NAT", "NAY", "NE", "NED", - "NEE", "NET", "NEW", "NIB", "NIL", "NIP", "NIT", "NO", "NOB", "NOD", - "NON", "NOR", "NOT", "NOV", "NOW", "NU", "NUN", "NUT", "O", "OAF", - "OAK", "OAR", "OAT", "ODD", "ODE", "OF", "OFF", "OFT", "OH", "OIL", - "OK", "OLD", "ON", "ONE", "OR", "ORB", "ORE", "ORR", "OS", "OTT", - "OUR", "OUT", "OVA", "OW", "OWE", "OWL", "OWN", "OX", "PA", "PAD", - "PAL", "PAM", "PAN", "PAP", "PAR", "PAT", "PAW", "PAY", "PEA", "PEG", - "PEN", "PEP", "PER", "PET", "PEW", "PHI", "PI", "PIE", "PIN", "PIT", - "PLY", "PO", "POD", "POE", "POP", "POT", "POW", "PRO", "PRY", "PUB", - "PUG", "PUN", "PUP", "PUT", "QUO", "RAG", "RAM", "RAN", "RAP", "RAT", - "RAW", "RAY", "REB", "RED", "REP", "RET", "RIB", "RID", "RIG", "RIM", - "RIO", "RIP", "ROB", "ROD", "ROE", "RON", "ROT", "ROW", "ROY", "RUB", - "RUE", "RUG", "RUM", "RUN", "RYE", "SAC", "SAD", "SAG", "SAL", "SAM", - "SAN", "SAP", "SAT", "SAW", "SAY", "SEA", "SEC", "SEE", "SEN", "SET", - "SEW", "SHE", "SHY", "SIN", "SIP", "SIR", "SIS", "SIT", "SKI", "SKY", - "SLY", "SO", "SOB", "SOD", "SON", "SOP", "SOW", "SOY", "SPA", "SPY", - "SUB", "SUD", "SUE", "SUM", "SUN", "SUP", "TAB", "TAD", "TAG", "TAN", - "TAP", "TAR", "TEA", "TED", "TEE", "TEN", "THE", "THY", "TIC", "TIE", - "TIM", "TIN", "TIP", "TO", "TOE", "TOG", "TOM", "TON", "TOO", "TOP", - "TOW", "TOY", "TRY", "TUB", "TUG", "TUM", "TUN", "TWO", "UN", "UP", - "US", "USE", "VAN", "VAT", "VET", "VIE", "WAD", "WAG", "WAR", "WAS", - "WAY", "WE", "WEB", "WED", "WEE", "WET", "WHO", "WHY", "WIN", "WIT", - "WOK", "WON", "WOO", "WOW", "WRY", "WU", "YAM", "YAP", "YAW", "YE", - "YEA", "YES", "YET", "YOU", "ABED", "ABEL", "ABET", "ABLE", "ABUT", - "ACHE", "ACID", "ACME", "ACRE", "ACTA", "ACTS", "ADAM", "ADDS", - "ADEN", "AFAR", "AFRO", "AGEE", "AHEM", "AHOY", "AIDA", "AIDE", - "AIDS", "AIRY", "AJAR", "AKIN", "ALAN", "ALEC", "ALGA", "ALIA", - "ALLY", "ALMA", "ALOE", "ALSO", "ALTO", "ALUM", "ALVA", "AMEN", - "AMES", "AMID", "AMMO", "AMOK", "AMOS", "AMRA", "ANDY", "ANEW", - "ANNA", "ANNE", "ANTE", "ANTI", "AQUA", "ARAB", "ARCH", "AREA", - "ARGO", "ARID", "ARMY", "ARTS", "ARTY", "ASIA", "ASKS", "ATOM", - "AUNT", "AURA", "AUTO", "AVER", "AVID", "AVIS", "AVON", "AVOW", - "AWAY", "AWRY", "BABE", "BABY", "BACH", "BACK", "BADE", "BAIL", - "BAIT", "BAKE", "BALD", "BALE", "BALI", "BALK", "BALL", "BALM", - "BAND", "BANE", "BANG", "BANK", "BARB", "BARD", "BARE", "BARK", - "BARN", "BARR", "BASE", "BASH", "BASK", "BASS", "BATE", "BATH", - "BAWD", "BAWL", "BEAD", "BEAK", "BEAM", "BEAN", "BEAR", "BEAT", - "BEAU", "BECK", "BEEF", "BEEN", "BEER", - "BEET", "BELA", "BELL", "BELT", "BEND", "BENT", "BERG", "BERN", - "BERT", "BESS", "BEST", "BETA", "BETH", "BHOY", "BIAS", "BIDE", - "BIEN", "BILE", "BILK", "BILL", "BIND", "BING", "BIRD", "BITE", - "BITS", "BLAB", "BLAT", "BLED", "BLEW", "BLOB", "BLOC", "BLOT", - "BLOW", "BLUE", "BLUM", "BLUR", "BOAR", "BOAT", "BOCA", "BOCK", - "BODE", "BODY", "BOGY", "BOHR", "BOIL", "BOLD", "BOLO", "BOLT", - "BOMB", "BONA", "BOND", "BONE", "BONG", "BONN", "BONY", "BOOK", - "BOOM", "BOON", "BOOT", "BORE", "BORG", "BORN", "BOSE", "BOSS", - "BOTH", "BOUT", "BOWL", "BOYD", "BRAD", "BRAE", "BRAG", "BRAN", - "BRAY", "BRED", "BREW", "BRIG", "BRIM", "BROW", "BUCK", "BUDD", - "BUFF", "BULB", "BULK", "BULL", "BUNK", "BUNT", "BUOY", "BURG", - "BURL", "BURN", "BURR", "BURT", "BURY", "BUSH", "BUSS", "BUST", - "BUSY", "BYTE", "CADY", "CAFE", "CAGE", "CAIN", "CAKE", "CALF", - "CALL", "CALM", "CAME", "CANE", "CANT", "CARD", "CARE", "CARL", - "CARR", "CART", "CASE", "CASH", "CASK", "CAST", "CAVE", "CEIL", - "CELL", "CENT", "CERN", "CHAD", "CHAR", "CHAT", "CHAW", "CHEF", - "CHEN", "CHEW", "CHIC", "CHIN", "CHOU", "CHOW", "CHUB", "CHUG", - "CHUM", "CITE", "CITY", "CLAD", "CLAM", "CLAN", "CLAW", "CLAY", - "CLOD", "CLOG", "CLOT", "CLUB", "CLUE", "COAL", "COAT", "COCA", - "COCK", "COCO", "CODA", "CODE", "CODY", "COED", "COIL", "COIN", - "COKE", "COLA", "COLD", "COLT", "COMA", "COMB", "COME", "COOK", - "COOL", "COON", "COOT", "CORD", "CORE", "CORK", "CORN", "COST", - "COVE", "COWL", "CRAB", "CRAG", "CRAM", "CRAY", "CREW", "CRIB", - "CROW", "CRUD", "CUBA", "CUBE", "CUFF", "CULL", "CULT", "CUNY", - "CURB", "CURD", "CURE", "CURL", "CURT", "CUTS", "DADE", "DALE", - "DAME", "DANA", "DANE", "DANG", "DANK", "DARE", "DARK", "DARN", - "DART", "DASH", "DATA", "DATE", "DAVE", "DAVY", "DAWN", "DAYS", - "DEAD", "DEAF", "DEAL", "DEAN", "DEAR", "DEBT", "DECK", "DEED", - "DEEM", "DEER", "DEFT", "DEFY", "DELL", "DENT", "DENY", "DESK", - "DIAL", "DICE", "DIED", "DIET", "DIME", "DINE", "DING", "DINT", - "DIRE", "DIRT", "DISC", "DISH", "DISK", "DIVE", "DOCK", "DOES", - "DOLE", "DOLL", "DOLT", "DOME", "DONE", "DOOM", "DOOR", "DORA", - "DOSE", "DOTE", "DOUG", "DOUR", "DOVE", "DOWN", "DRAB", "DRAG", - "DRAM", "DRAW", "DREW", "DRUB", "DRUG", "DRUM", "DUAL", "DUCK", - "DUCT", "DUEL", "DUET", "DUKE", "DULL", "DUMB", "DUNE", "DUNK", - "DUSK", "DUST", "DUTY", "EACH", "EARL", "EARN", "EASE", "EAST", - "EASY", "EBEN", "ECHO", "EDDY", "EDEN", "EDGE", "EDGY", "EDIT", - "EDNA", "EGAN", "ELAN", "ELBA", "ELLA", "ELSE", "EMIL", "EMIT", - "EMMA", "ENDS", "ERIC", "EROS", "EVEN", "EVER", "EVIL", "EYED", - "FACE", "FACT", "FADE", "FAIL", "FAIN", "FAIR", "FAKE", "FALL", - "FAME", "FANG", "FARM", "FAST", "FATE", "FAWN", "FEAR", "FEAT", - "FEED", "FEEL", "FEET", "FELL", "FELT", "FEND", "FERN", "FEST", - "FEUD", "FIEF", "FIGS", "FILE", "FILL", "FILM", "FIND", "FINE", - "FINK", "FIRE", "FIRM", "FISH", "FISK", "FIST", "FITS", "FIVE", - "FLAG", "FLAK", "FLAM", "FLAT", "FLAW", "FLEA", "FLED", "FLEW", - "FLIT", "FLOC", "FLOG", "FLOW", "FLUB", "FLUE", "FOAL", "FOAM", - "FOGY", "FOIL", "FOLD", "FOLK", "FOND", "FONT", "FOOD", "FOOL", - "FOOT", "FORD", "FORE", "FORK", "FORM", "FORT", "FOSS", "FOUL", - "FOUR", "FOWL", "FRAU", "FRAY", "FRED", "FREE", "FRET", "FREY", - "FROG", "FROM", "FUEL", "FULL", "FUME", "FUND", "FUNK", "FURY", - "FUSE", "FUSS", "GAFF", "GAGE", "GAIL", "GAIN", "GAIT", "GALA", - "GALE", "GALL", "GALT", "GAME", "GANG", "GARB", "GARY", "GASH", - "GATE", "GAUL", "GAUR", "GAVE", "GAWK", "GEAR", "GELD", "GENE", - "GENT", "GERM", "GETS", "GIBE", "GIFT", "GILD", "GILL", "GILT", - "GINA", "GIRD", "GIRL", "GIST", "GIVE", "GLAD", "GLEE", "GLEN", - "GLIB", "GLOB", "GLOM", "GLOW", "GLUE", "GLUM", "GLUT", "GOAD", - "GOAL", "GOAT", "GOER", "GOES", "GOLD", "GOLF", "GONE", "GONG", - "GOOD", "GOOF", "GORE", "GORY", "GOSH", "GOUT", "GOWN", "GRAB", - "GRAD", "GRAY", "GREG", "GREW", "GREY", "GRID", "GRIM", "GRIN", - "GRIT", "GROW", "GRUB", "GULF", "GULL", "GUNK", "GURU", "GUSH", - "GUST", "GWEN", "GWYN", "HAAG", "HAAS", "HACK", "HAIL", "HAIR", - "HALE", "HALF", "HALL", "HALO", "HALT", "HAND", "HANG", "HANK", - "HANS", "HARD", "HARK", "HARM", "HART", "HASH", "HAST", "HATE", - "HATH", "HAUL", "HAVE", "HAWK", "HAYS", "HEAD", "HEAL", "HEAR", - "HEAT", "HEBE", "HECK", "HEED", "HEEL", "HEFT", "HELD", "HELL", - "HELM", "HERB", "HERD", "HERE", "HERO", "HERS", "HESS", "HEWN", - "HICK", "HIDE", "HIGH", "HIKE", "HILL", "HILT", "HIND", "HINT", - "HIRE", "HISS", "HIVE", "HOBO", "HOCK", "HOFF", "HOLD", "HOLE", - "HOLM", "HOLT", "HOME", "HONE", "HONK", "HOOD", "HOOF", "HOOK", - "HOOT", "HORN", "HOSE", "HOST", "HOUR", "HOVE", "HOWE", "HOWL", - "HOYT", "HUCK", "HUED", "HUFF", "HUGE", "HUGH", "HUGO", "HULK", - "HULL", "HUNK", "HUNT", "HURD", "HURL", "HURT", "HUSH", "HYDE", - "HYMN", "IBIS", "ICON", "IDEA", "IDLE", "IFFY", "INCA", "INCH", - "INTO", "IONS", "IOTA", "IOWA", "IRIS", "IRMA", "IRON", "ISLE", - "ITCH", "ITEM", "IVAN", "JACK", "JADE", "JAIL", "JAKE", "JANE", - "JAVA", "JEAN", "JEFF", "JERK", "JESS", "JEST", "JIBE", "JILL", - "JILT", "JIVE", "JOAN", "JOBS", "JOCK", "JOEL", "JOEY", "JOHN", - "JOIN", "JOKE", "JOLT", "JOVE", "JUDD", "JUDE", "JUDO", "JUDY", - "JUJU", "JUKE", "JULY", "JUNE", "JUNK", "JUNO", "JURY", "JUST", - "JUTE", "KAHN", "KALE", "KANE", "KANT", "KARL", "KATE", "KEEL", - "KEEN", "KENO", "KENT", "KERN", "KERR", "KEYS", "KICK", "KILL", - "KIND", "KING", "KIRK", "KISS", "KITE", "KLAN", "KNEE", "KNEW", - "KNIT", "KNOB", "KNOT", "KNOW", "KOCH", "KONG", "KUDO", "KURD", - "KURT", "KYLE", "LACE", "LACK", "LACY", "LADY", "LAID", "LAIN", - "LAIR", "LAKE", "LAMB", "LAME", "LAND", "LANE", "LANG", "LARD", - "LARK", "LASS", "LAST", "LATE", "LAUD", "LAVA", "LAWN", "LAWS", - "LAYS", "LEAD", "LEAF", "LEAK", "LEAN", "LEAR", "LEEK", "LEER", - "LEFT", "LEND", "LENS", "LENT", "LEON", "LESK", "LESS", "LEST", - "LETS", "LIAR", "LICE", "LICK", "LIED", "LIEN", "LIES", "LIEU", - "LIFE", "LIFT", "LIKE", "LILA", "LILT", "LILY", "LIMA", "LIMB", - "LIME", "LIND", "LINE", "LINK", "LINT", "LION", "LISA", "LIST", - "LIVE", "LOAD", "LOAF", "LOAM", "LOAN", "LOCK", "LOFT", "LOGE", - "LOIS", "LOLA", "LONE", "LONG", "LOOK", "LOON", "LOOT", "LORD", - "LORE", "LOSE", "LOSS", "LOST", "LOUD", "LOVE", "LOWE", "LUCK", - "LUCY", "LUGE", "LUKE", "LULU", "LUND", "LUNG", "LURA", "LURE", - "LURK", "LUSH", "LUST", "LYLE", "LYNN", "LYON", "LYRA", "MACE", - "MADE", "MAGI", "MAID", "MAIL", "MAIN", "MAKE", "MALE", "MALI", - "MALL", "MALT", "MANA", "MANN", "MANY", "MARC", "MARE", "MARK", - "MARS", "MART", "MARY", "MASH", "MASK", "MASS", "MAST", "MATE", - "MATH", "MAUL", "MAYO", "MEAD", "MEAL", "MEAN", "MEAT", "MEEK", - "MEET", "MELD", "MELT", "MEMO", "MEND", "MENU", "MERT", "MESH", - "MESS", "MICE", "MIKE", "MILD", "MILE", "MILK", "MILL", "MILT", - "MIMI", "MIND", "MINE", "MINI", "MINK", "MINT", "MIRE", "MISS", - "MIST", "MITE", "MITT", "MOAN", "MOAT", "MOCK", "MODE", "MOLD", - "MOLE", "MOLL", "MOLT", "MONA", "MONK", "MONT", "MOOD", "MOON", - "MOOR", "MOOT", "MORE", "MORN", "MORT", "MOSS", "MOST", "MOTH", - "MOVE", "MUCH", "MUCK", "MUDD", "MUFF", "MULE", "MULL", "MURK", - "MUSH", "MUST", "MUTE", "MUTT", "MYRA", "MYTH", "NAGY", "NAIL", - "NAIR", "NAME", "NARY", "NASH", "NAVE", "NAVY", "NEAL", "NEAR", - "NEAT", "NECK", "NEED", "NEIL", "NELL", "NEON", "NERO", "NESS", - "NEST", "NEWS", "NEWT", "NIBS", "NICE", "NICK", "NILE", "NINA", - "NINE", "NOAH", "NODE", "NOEL", "NOLL", "NONE", "NOOK", "NOON", - "NORM", "NOSE", "NOTE", "NOUN", "NOVA", "NUDE", "NULL", "NUMB", - "OATH", "OBEY", "OBOE", "ODIN", "OHIO", "OILY", "OINT", "OKAY", - "OLAF", "OLDY", "OLGA", "OLIN", "OMAN", "OMEN", "OMIT", "ONCE", - "ONES", "ONLY", "ONTO", "ONUS", "ORAL", "ORGY", "OSLO", "OTIS", - "OTTO", "OUCH", "OUST", "OUTS", "OVAL", "OVEN", "OVER", "OWLY", - "OWNS", "QUAD", "QUIT", "QUOD", "RACE", "RACK", "RACY", "RAFT", - "RAGE", "RAID", "RAIL", "RAIN", "RAKE", "RANK", "RANT", "RARE", - "RASH", "RATE", "RAVE", "RAYS", "READ", "REAL", "REAM", "REAR", - "RECK", "REED", "REEF", "REEK", "REEL", "REID", "REIN", "RENA", - "REND", "RENT", "REST", "RICE", "RICH", "RICK", "RIDE", "RIFT", - "RILL", "RIME", "RING", "RINK", "RISE", "RISK", "RITE", "ROAD", - "ROAM", "ROAR", "ROBE", "ROCK", "RODE", "ROIL", "ROLL", "ROME", - "ROOD", "ROOF", "ROOK", "ROOM", "ROOT", "ROSA", "ROSE", "ROSS", - "ROSY", "ROTH", "ROUT", "ROVE", "ROWE", "ROWS", "RUBE", "RUBY", - "RUDE", "RUDY", "RUIN", "RULE", "RUNG", "RUNS", "RUNT", "RUSE", - "RUSH", "RUSK", "RUSS", "RUST", "RUTH", "SACK", "SAFE", "SAGE", - "SAID", "SAIL", "SALE", "SALK", "SALT", "SAME", "SAND", "SANE", - "SANG", "SANK", "SARA", "SAUL", "SAVE", "SAYS", "SCAN", "SCAR", - "SCAT", "SCOT", "SEAL", "SEAM", "SEAR", "SEAT", "SEED", "SEEK", - "SEEM", "SEEN", "SEES", "SELF", "SELL", "SEND", "SENT", "SETS", - "SEWN", "SHAG", "SHAM", "SHAW", "SHAY", "SHED", "SHIM", "SHIN", - "SHOD", "SHOE", "SHOT", "SHOW", "SHUN", "SHUT", "SICK", "SIDE", - "SIFT", "SIGH", "SIGN", "SILK", "SILL", "SILO", "SILT", "SINE", - "SING", "SINK", "SIRE", "SITE", "SITS", "SITU", "SKAT", "SKEW", - "SKID", "SKIM", "SKIN", "SKIT", "SLAB", "SLAM", "SLAT", "SLAY", - "SLED", "SLEW", "SLID", "SLIM", "SLIT", "SLOB", "SLOG", "SLOT", - "SLOW", "SLUG", "SLUM", "SLUR", "SMOG", "SMUG", "SNAG", "SNOB", - "SNOW", "SNUB", "SNUG", "SOAK", "SOAR", "SOCK", "SODA", "SOFA", - "SOFT", "SOIL", "SOLD", "SOME", "SONG", "SOON", "SOOT", "SORE", - "SORT", "SOUL", "SOUR", "SOWN", "STAB", "STAG", "STAN", "STAR", - "STAY", "STEM", "STEW", "STIR", "STOW", "STUB", "STUN", "SUCH", - "SUDS", "SUIT", "SULK", "SUMS", "SUNG", "SUNK", "SURE", "SURF", - "SWAB", "SWAG", "SWAM", "SWAN", "SWAT", "SWAY", "SWIM", "SWUM", - "TACK", "TACT", "TAIL", "TAKE", "TALE", "TALK", "TALL", "TANK", - "TASK", "TATE", "TAUT", "TEAL", "TEAM", "TEAR", "TECH", "TEEM", - "TEEN", "TEET", "TELL", "TEND", "TENT", "TERM", "TERN", "TESS", - "TEST", "THAN", "THAT", "THEE", "THEM", "THEN", "THEY", "THIN", - "THIS", "THUD", "THUG", "TICK", "TIDE", "TIDY", "TIED", "TIER", - "TILE", "TILL", "TILT", "TIME", "TINA", "TINE", "TINT", "TINY", - "TIRE", "TOAD", "TOGO", "TOIL", "TOLD", "TOLL", "TONE", "TONG", - "TONY", "TOOK", "TOOL", "TOOT", "TORE", "TORN", "TOTE", "TOUR", - "TOUT", "TOWN", "TRAG", "TRAM", "TRAY", "TREE", "TREK", "TRIG", - "TRIM", "TRIO", "TROD", "TROT", "TROY", "TRUE", "TUBA", "TUBE", - "TUCK", "TUFT", "TUNA", "TUNE", "TUNG", "TURF", "TURN", "TUSK", - "TWIG", "TWIN", "TWIT", "ULAN", "UNIT", "URGE", "USED", "USER", - "USES", "UTAH", "VAIL", "VAIN", "VALE", "VARY", "VASE", "VAST", - "VEAL", "VEDA", "VEIL", "VEIN", "VEND", "VENT", "VERB", "VERY", - "VETO", "VICE", "VIEW", "VINE", "VISE", "VOID", "VOLT", "VOTE", - "WACK", "WADE", "WAGE", "WAIL", "WAIT", "WAKE", "WALE", "WALK", - "WALL", "WALT", "WAND", "WANE", "WANG", "WANT", "WARD", "WARM", - "WARN", "WART", "WASH", "WAST", "WATS", "WATT", "WAVE", "WAVY", - "WAYS", "WEAK", "WEAL", "WEAN", "WEAR", "WEED", "WEEK", "WEIR", - "WELD", "WELL", "WELT", "WENT", "WERE", "WERT", "WEST", "WHAM", - "WHAT", "WHEE", "WHEN", "WHET", "WHOA", "WHOM", "WICK", "WIFE", - "WILD", "WILL", "WIND", "WINE", "WING", "WINK", "WINO", "WIRE", - "WISE", "WISH", "WITH", "WOLF", "WONT", "WOOD", "WOOL", "WORD", - "WORE", "WORK", "WORM", "WORN", "WOVE", "WRIT", "WYNN", "YALE", - "YANG", "YANK", "YARD", "YARN", "YAWL", "YAWN", "YEAH", "YEAR", - "YELL", "YOGA", "YOKE" ] diff --git a/Crypto/Util/RFC1751.pyi b/Crypto/Util/RFC1751.pyi deleted file mode 100644 index 6ad07ff..0000000 --- a/Crypto/Util/RFC1751.pyi +++ /dev/null @@ -1,7 +0,0 @@ -from typing import Dict, List - -binary: Dict[int, str] -wordlist: List[str] - -def key_to_english(key: bytes) -> str: ... -def english_to_key(s: str) -> bytes: ... diff --git a/Crypto/Util/__init__.py b/Crypto/Util/__init__.py deleted file mode 100644 index f12214d..0000000 --- a/Crypto/Util/__init__.py +++ /dev/null @@ -1,41 +0,0 @@ -# -*- coding: utf-8 -*- -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== - -"""Miscellaneous modules - -Contains useful modules that don't belong into any of the -other Crypto.* subpackages. - -======================== ============================================= -Module Description -======================== ============================================= -`Crypto.Util.number` Number-theoretic functions (primality testing, etc.) -`Crypto.Util.Counter` Fast counter functions for CTR cipher modes. -`Crypto.Util.RFC1751` Converts between 128-bit keys and human-readable - strings of words. -`Crypto.Util.asn1` Minimal support for ASN.1 DER encoding -`Crypto.Util.Padding` Set of functions for adding and removing padding. -======================== ============================================= - -:undocumented: _galois, _number_new, cpuid, py3compat, _raw_api -""" - -__all__ = ['RFC1751', 'number', 'strxor', 'asn1', 'Counter', 'Padding'] - diff --git a/Crypto/Util/__pycache__/__init__.cpython-36.pyc b/Crypto/Util/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index 4df4eef..0000000 Binary files a/Crypto/Util/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Util/__pycache__/_cpu_features.cpython-36.pyc b/Crypto/Util/__pycache__/_cpu_features.cpython-36.pyc deleted file mode 100644 index f4240fd..0000000 Binary files a/Crypto/Util/__pycache__/_cpu_features.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Util/__pycache__/_file_system.cpython-36.pyc b/Crypto/Util/__pycache__/_file_system.cpython-36.pyc deleted file mode 100644 index 170de6f..0000000 Binary files a/Crypto/Util/__pycache__/_file_system.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Util/__pycache__/_raw_api.cpython-36.pyc b/Crypto/Util/__pycache__/_raw_api.cpython-36.pyc deleted file mode 100644 index 7e9cb23..0000000 Binary files a/Crypto/Util/__pycache__/_raw_api.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Util/__pycache__/number.cpython-36.pyc b/Crypto/Util/__pycache__/number.cpython-36.pyc deleted file mode 100644 index d9ef26b..0000000 Binary files a/Crypto/Util/__pycache__/number.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Util/__pycache__/py3compat.cpython-36.pyc b/Crypto/Util/__pycache__/py3compat.cpython-36.pyc deleted file mode 100644 index 11e5771..0000000 Binary files a/Crypto/Util/__pycache__/py3compat.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Util/__pycache__/strxor.cpython-36.pyc b/Crypto/Util/__pycache__/strxor.cpython-36.pyc deleted file mode 100644 index 7ae90da..0000000 Binary files a/Crypto/Util/__pycache__/strxor.cpython-36.pyc and /dev/null differ diff --git a/Crypto/Util/_cpu_features.py b/Crypto/Util/_cpu_features.py deleted file mode 100644 index b3039b5..0000000 --- a/Crypto/Util/_cpu_features.py +++ /dev/null @@ -1,46 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2018, Helder Eijs -# 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 Crypto.Util._raw_api import load_pycryptodome_raw_lib - - -_raw_cpuid_lib = load_pycryptodome_raw_lib("Crypto.Util._cpuid_c", - """ - int have_aes_ni(void); - int have_clmul(void); - """) - - -def have_aes_ni(): - return _raw_cpuid_lib.have_aes_ni() - - -def have_clmul(): - return _raw_cpuid_lib.have_clmul() diff --git a/Crypto/Util/_cpu_features.pyi b/Crypto/Util/_cpu_features.pyi deleted file mode 100644 index 10e669e..0000000 --- a/Crypto/Util/_cpu_features.pyi +++ /dev/null @@ -1,2 +0,0 @@ -def have_aes_ni() -> int: ... -def have_clmul() -> int: ... diff --git a/Crypto/Util/_cpuid_c.abi3.so b/Crypto/Util/_cpuid_c.abi3.so deleted file mode 100644 index 2a7ec30..0000000 Binary files a/Crypto/Util/_cpuid_c.abi3.so and /dev/null differ diff --git a/Crypto/Util/_file_system.py b/Crypto/Util/_file_system.py deleted file mode 100644 index 1cb0c4b..0000000 --- a/Crypto/Util/_file_system.py +++ /dev/null @@ -1,54 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2016, Legrandin -# 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 - - -def pycryptodome_filename(dir_comps, filename): - """Return the complete file name for the module - - dir_comps : list of string - The list of directory names in the PyCryptodome package. - The first element must be "Crypto". - - filename : string - The filename (inclusing extension) in the target directory. - """ - - if dir_comps[0] != "Crypto": - raise ValueError("Only available for modules under 'Crypto'") - - dir_comps = list(dir_comps[1:]) + [filename] - - util_lib, _ = os.path.split(os.path.abspath(__file__)) - root_lib = os.path.join(util_lib, "..") - - return os.path.join(root_lib, *dir_comps) - diff --git a/Crypto/Util/_file_system.pyi b/Crypto/Util/_file_system.pyi deleted file mode 100644 index d54a126..0000000 --- a/Crypto/Util/_file_system.pyi +++ /dev/null @@ -1,4 +0,0 @@ -from typing import List - - -def pycryptodome_filename(dir_comps: List[str], filename: str) -> str: ... \ No newline at end of file diff --git a/Crypto/Util/_raw_api.py b/Crypto/Util/_raw_api.py deleted file mode 100644 index 44c37c2..0000000 --- a/Crypto/Util/_raw_api.py +++ /dev/null @@ -1,307 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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 abc -import sys -from Crypto.Util.py3compat import byte_string -from Crypto.Util._file_system import pycryptodome_filename - -# -# List of file suffixes for Python extensions -# -if sys.version_info[0] < 3: - - import imp - extension_suffixes = [] - for ext, mod, typ in imp.get_suffixes(): - if typ == imp.C_EXTENSION: - extension_suffixes.append(ext) - -else: - - from importlib import machinery - extension_suffixes = machinery.EXTENSION_SUFFIXES - -# Which types with buffer interface we support (apart from byte strings) -_buffer_type = (bytearray, memoryview) - - -class _VoidPointer(object): - @abc.abstractmethod - def get(self): - """Return the memory location we point to""" - return - - @abc.abstractmethod - def address_of(self): - """Return a raw pointer to this pointer""" - return - - -try: - # Starting from v2.18, pycparser (used by cffi for in-line ABI mode) - # stops working correctly when PYOPTIMIZE==2 or the parameter -OO is - # passed. In that case, we fall back to ctypes. - # Note that PyPy ships with an old version of pycparser so we can keep - # using cffi there. - # See https://github.com/Legrandin/pycryptodome/issues/228 - if '__pypy__' not in sys.builtin_module_names and sys.flags.optimize == 2: - raise ImportError("CFFI with optimize=2 fails due to pycparser bug.") - - from cffi import FFI - - ffi = FFI() - null_pointer = ffi.NULL - uint8_t_type = ffi.typeof(ffi.new("const uint8_t*")) - - _Array = ffi.new("uint8_t[1]").__class__.__bases__ - - def load_lib(name, cdecl): - """Load a shared library and return a handle to it. - - @name, either an absolute path or the name of a library - in the system search path. - - @cdecl, the C function declarations. - """ - - lib = ffi.dlopen(name) - ffi.cdef(cdecl) - return lib - - def c_ulong(x): - """Convert a Python integer to unsigned long""" - return x - - c_ulonglong = c_ulong - c_uint = c_ulong - - def c_size_t(x): - """Convert a Python integer to size_t""" - return x - - def create_string_buffer(init_or_size, size=None): - """Allocate the given amount of bytes (initially set to 0)""" - - if isinstance(init_or_size, bytes): - size = max(len(init_or_size) + 1, size) - result = ffi.new("uint8_t[]", size) - result[:] = init_or_size - else: - if size: - raise ValueError("Size must be specified once only") - result = ffi.new("uint8_t[]", init_or_size) - return result - - def get_c_string(c_string): - """Convert a C string into a Python byte sequence""" - return ffi.string(c_string) - - def get_raw_buffer(buf): - """Convert a C buffer into a Python byte sequence""" - return ffi.buffer(buf)[:] - - def c_uint8_ptr(data): - if isinstance(data, _buffer_type): - # This only works for cffi >= 1.7 - return ffi.cast(uint8_t_type, ffi.from_buffer(data)) - elif byte_string(data) or isinstance(data, _Array): - return data - else: - raise TypeError("Object type %s cannot be passed to C code" % type(data)) - - class VoidPointer_cffi(_VoidPointer): - """Model a newly allocated pointer to void""" - - def __init__(self): - self._pp = ffi.new("void *[1]") - - def get(self): - return self._pp[0] - - def address_of(self): - return self._pp - - def VoidPointer(): - return VoidPointer_cffi() - - backend = "cffi" - -except ImportError: - - import ctypes - from ctypes import (CDLL, c_void_p, byref, c_ulong, c_ulonglong, c_size_t, - create_string_buffer, c_ubyte, c_uint) - from ctypes.util import find_library - from ctypes import Array as _Array - - null_pointer = None - cached_architecture = [] - - def load_lib(name, cdecl): - if not cached_architecture: - # platform.architecture() creates a subprocess, so caching the - # result makes successive imports faster. - import platform - cached_architecture[:] = platform.architecture() - bits, linkage = cached_architecture - if "." not in name and not linkage.startswith("Win"): - full_name = find_library(name) - if full_name is None: - raise OSError("Cannot load library '%s'" % name) - name = full_name - return CDLL(name) - - def get_c_string(c_string): - return c_string.value - - def get_raw_buffer(buf): - return buf.raw - - # ---- Get raw pointer --- - - _c_ssize_t = ctypes.c_ssize_t - - _PyBUF_SIMPLE = 0 - _PyObject_GetBuffer = ctypes.pythonapi.PyObject_GetBuffer - _PyBuffer_Release = ctypes.pythonapi.PyBuffer_Release - _py_object = ctypes.py_object - _c_ssize_p = ctypes.POINTER(_c_ssize_t) - - # See Include/object.h for CPython - # and https://github.com/pallets/click/blob/master/click/_winconsole.py - class _Py_buffer(ctypes.Structure): - _fields_ = [ - ('buf', c_void_p), - ('obj', ctypes.py_object), - ('len', _c_ssize_t), - ('itemsize', _c_ssize_t), - ('readonly', ctypes.c_int), - ('ndim', ctypes.c_int), - ('format', ctypes.c_char_p), - ('shape', _c_ssize_p), - ('strides', _c_ssize_p), - ('suboffsets', _c_ssize_p), - ('internal', c_void_p) - ] - - # Extra field for CPython 2.6/2.7 - if sys.version_info[0] == 2: - _fields_.insert(-1, ('smalltable', _c_ssize_t * 2)) - - def c_uint8_ptr(data): - if byte_string(data) or isinstance(data, _Array): - return data - elif isinstance(data, _buffer_type): - obj = _py_object(data) - buf = _Py_buffer() - _PyObject_GetBuffer(obj, byref(buf), _PyBUF_SIMPLE) - try: - buffer_type = c_ubyte * buf.len - return buffer_type.from_address(buf.buf) - finally: - _PyBuffer_Release(byref(buf)) - else: - raise TypeError("Object type %s cannot be passed to C code" % type(data)) - - # --- - - class VoidPointer_ctypes(_VoidPointer): - """Model a newly allocated pointer to void""" - - def __init__(self): - self._p = c_void_p() - - def get(self): - return self._p - - def address_of(self): - return byref(self._p) - - def VoidPointer(): - return VoidPointer_ctypes() - - backend = "ctypes" - del ctypes - - -class SmartPointer(object): - """Class to hold a non-managed piece of memory""" - - def __init__(self, raw_pointer, destructor): - self._raw_pointer = raw_pointer - self._destructor = destructor - - def get(self): - return self._raw_pointer - - def release(self): - rp, self._raw_pointer = self._raw_pointer, None - return rp - - def __del__(self): - try: - if self._raw_pointer is not None: - self._destructor(self._raw_pointer) - self._raw_pointer = None - except AttributeError: - pass - - -def load_pycryptodome_raw_lib(name, cdecl): - """Load a shared library and return a handle to it. - - @name, the name of the library expressed as a PyCryptodome module, - for instance Crypto.Cipher._raw_cbc. - - @cdecl, the C function declarations. - """ - - split = name.split(".") - dir_comps, basename = split[:-1], split[-1] - attempts = [] - for ext in extension_suffixes: - try: - filename = basename + ext - return load_lib(pycryptodome_filename(dir_comps, filename), - cdecl) - except OSError as exp: - attempts.append("Trying '%s': %s" % (filename, str(exp))) - raise OSError("Cannot load native module '%s': %s" % (name, ", ".join(attempts))) - - -def is_buffer(x): - """Return True if object x supports the buffer interface""" - return isinstance(x, (bytes, bytearray, memoryview)) - - -def is_writeable_buffer(x): - return (isinstance(x, bytearray) or - (isinstance(x, memoryview) and not x.readonly)) diff --git a/Crypto/Util/_raw_api.pyi b/Crypto/Util/_raw_api.pyi deleted file mode 100644 index 2bc5301..0000000 --- a/Crypto/Util/_raw_api.pyi +++ /dev/null @@ -1,27 +0,0 @@ -from typing import Any, Optional, Union - -def load_lib(name: str, cdecl: str) -> Any : ... -def c_ulong(x: int ) -> Any : ... -def c_ulonglong(x: int ) -> Any : ... -def c_size_t(x: int) -> Any : ... -def create_string_buffer(init_or_size: Union[bytes,int], size: Optional[int]) -> Any : ... -def get_c_string(c_string: Any) -> bytes : ... -def get_raw_buffer(buf: Any) -> bytes : ... -def c_uint8_ptr(data: Union[bytes, memoryview, bytearray]) -> Any : ... - -class VoidPointer(object): - def get(self) -> Any : ... - def address_of(self) -> Any : ... - -class SmartPointer(object): - def __init__(self, raw_pointer: Any, destructor: Any) -> None : ... - def get(self) -> Any : ... - def release(self) -> Any : ... - -backend : str -null_pointer : Any -ffi: Any - -def load_pycryptodome_raw_lib(name: str, cdecl: str) -> Any : ... -def is_buffer(x: Any) -> bool : ... -def is_writeable_buffer(x: Any) -> bool : ... diff --git a/Crypto/Util/_strxor.abi3.so b/Crypto/Util/_strxor.abi3.so deleted file mode 100644 index efecda2..0000000 Binary files a/Crypto/Util/_strxor.abi3.so and /dev/null differ diff --git a/Crypto/Util/asn1.py b/Crypto/Util/asn1.py deleted file mode 100644 index ec9aacd..0000000 --- a/Crypto/Util/asn1.py +++ /dev/null @@ -1,940 +0,0 @@ -# -*- coding: ascii -*- -# -# Util/asn1.py : Minimal support for ASN.1 DER binary encoding. -# -# =================================================================== -# 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 struct - -from Crypto.Util.py3compat import byte_string, b, bchr, bord - -from Crypto.Util.number import long_to_bytes, bytes_to_long - -__all__ = ['DerObject', 'DerInteger', 'DerOctetString', 'DerNull', - 'DerSequence', 'DerObjectId', 'DerBitString', 'DerSetOf'] - - -def _is_number(x, only_non_negative=False): - test = 0 - try: - test = x + test - except TypeError: - return False - return not only_non_negative or x >= 0 - - -class BytesIO_EOF(object): - """This class differs from BytesIO in that a ValueError exception is - raised whenever EOF is reached.""" - - def __init__(self, initial_bytes): - self._buffer = initial_bytes - self._index = 0 - self._bookmark = None - - def set_bookmark(self): - self._bookmark = self._index - - def data_since_bookmark(self): - assert self._bookmark is not None - return self._buffer[self._bookmark:self._index] - - def remaining_data(self): - return len(self._buffer) - self._index - - def read(self, length): - new_index = self._index + length - if new_index > len(self._buffer): - raise ValueError("Not enough data for DER decoding: expected %d bytes and found %d" % (new_index, len(self._buffer))) - - result = self._buffer[self._index:new_index] - self._index = new_index - return result - - def read_byte(self): - return bord(self.read(1)[0]) - - -class DerObject(object): - """Base class for defining a single DER object. - - This class should never be directly instantiated. - """ - - def __init__(self, asn1Id=None, payload=b'', implicit=None, - constructed=False, explicit=None): - """Initialize the DER object according to a specific ASN.1 type. - - :Parameters: - asn1Id : integer - The universal DER tag number for this object - (e.g. 0x10 for a SEQUENCE). - If None, the tag is not known yet. - - payload : byte string - The initial payload of the object (that it, - the content octets). - If not specified, the payload is empty. - - implicit : integer - The IMPLICIT tag number to use for the encoded object. - It overrides the universal tag *asn1Id*. - - constructed : bool - True when the ASN.1 type is *constructed*. - False when it is *primitive*. - - explicit : integer - The EXPLICIT tag number to use for the encoded object. - """ - - if asn1Id is None: - # The tag octet will be read in with ``decode`` - self._tag_octet = None - return - asn1Id = self._convertTag(asn1Id) - - self.payload = payload - - # In a BER/DER identifier octet: - # * bits 4-0 contain the tag value - # * bit 5 is set if the type is 'constructed' - # and unset if 'primitive' - # * bits 7-6 depend on the encoding class - # - # Class | Bit 7, Bit 6 - # ---------------------------------- - # universal | 0 0 - # application | 0 1 - # context-spec | 1 0 (default for IMPLICIT/EXPLICIT) - # private | 1 1 - # - if None not in (explicit, implicit): - raise ValueError("Explicit and implicit tags are" - " mutually exclusive") - - if implicit is not None: - self._tag_octet = 0x80 | 0x20 * constructed | self._convertTag(implicit) - return - - if explicit is not None: - self._tag_octet = 0xA0 | self._convertTag(explicit) - self._inner_tag_octet = 0x20 * constructed | asn1Id - return - - self._tag_octet = 0x20 * constructed | asn1Id - - def _convertTag(self, tag): - """Check if *tag* is a real DER tag. - Convert it from a character to number if necessary. - """ - if not _is_number(tag): - if len(tag) == 1: - tag = bord(tag[0]) - # Ensure that tag is a low tag - if not (_is_number(tag) and 0 <= tag < 0x1F): - raise ValueError("Wrong DER tag") - return tag - - @staticmethod - def _definite_form(length): - """Build length octets according to BER/DER - definite form. - """ - if length > 127: - encoding = long_to_bytes(length) - return bchr(len(encoding) + 128) + encoding - return bchr(length) - - def encode(self): - """Return this DER element, fully encoded as a binary byte string.""" - - # Concatenate identifier octets, length octets, - # and contents octets - - output_payload = self.payload - - # In case of an EXTERNAL tag, first encode the inner - # element. - if hasattr(self, "_inner_tag_octet"): - output_payload = (bchr(self._inner_tag_octet) + - self._definite_form(len(self.payload)) + - self.payload) - - return (bchr(self._tag_octet) + - self._definite_form(len(output_payload)) + - output_payload) - - def _decodeLen(self, s): - """Decode DER length octets from a file.""" - - length = s.read_byte() - - if length > 127: - encoded_length = s.read(length & 0x7F) - if bord(encoded_length[0]) == 0: - raise ValueError("Invalid DER: length has leading zero") - length = bytes_to_long(encoded_length) - if length <= 127: - raise ValueError("Invalid DER: length in long form but smaller than 128") - - return length - - def decode(self, der_encoded, strict=False): - """Decode a complete DER element, and re-initializes this - object with it. - - Args: - der_encoded (byte string): A complete DER element. - - Raises: - ValueError: in case of parsing errors. - """ - - if not byte_string(der_encoded): - raise ValueError("Input is not a byte string") - - s = BytesIO_EOF(der_encoded) - self._decodeFromStream(s, strict) - - # There shouldn't be other bytes left - if s.remaining_data() > 0: - raise ValueError("Unexpected extra data after the DER structure") - - return self - - def _decodeFromStream(self, s, strict): - """Decode a complete DER element from a file.""" - - idOctet = s.read_byte() - if self._tag_octet is not None: - if idOctet != self._tag_octet: - raise ValueError("Unexpected DER tag") - else: - self._tag_octet = idOctet - length = self._decodeLen(s) - self.payload = s.read(length) - - # In case of an EXTERNAL tag, further decode the inner - # element. - if hasattr(self, "_inner_tag_octet"): - p = BytesIO_EOF(self.payload) - inner_octet = p.read_byte() - if inner_octet != self._inner_tag_octet: - raise ValueError("Unexpected internal DER tag") - length = self._decodeLen(p) - self.payload = p.read(length) - - # There shouldn't be other bytes left - if p.remaining_data() > 0: - raise ValueError("Unexpected extra data after the DER structure") - - -class DerInteger(DerObject): - """Class to model a DER INTEGER. - - An example of encoding is:: - - >>> from Crypto.Util.asn1 import DerInteger - >>> from binascii import hexlify, unhexlify - >>> int_der = DerInteger(9) - >>> print hexlify(int_der.encode()) - - which will show ``020109``, the DER encoding of 9. - - And for decoding:: - - >>> s = unhexlify(b'020109') - >>> try: - >>> int_der = DerInteger() - >>> int_der.decode(s) - >>> print int_der.value - >>> except ValueError: - >>> print "Not a valid DER INTEGER" - - the output will be ``9``. - - :ivar value: The integer value - :vartype value: integer - """ - - def __init__(self, value=0, implicit=None, explicit=None): - """Initialize the DER object as an INTEGER. - - :Parameters: - value : integer - The value of the integer. - - implicit : integer - The IMPLICIT tag to use for the encoded object. - It overrides the universal tag for INTEGER (2). - """ - - DerObject.__init__(self, 0x02, b'', implicit, - False, explicit) - self.value = value # The integer value - - def encode(self): - """Return the DER INTEGER, fully encoded as a - binary string.""" - - number = self.value - self.payload = b'' - while True: - self.payload = bchr(int(number & 255)) + self.payload - if 128 <= number <= 255: - self.payload = bchr(0x00) + self.payload - if -128 <= number <= 255: - break - number >>= 8 - return DerObject.encode(self) - - def decode(self, der_encoded, strict=False): - """Decode a complete DER INTEGER DER, and re-initializes this - object with it. - - Args: - der_encoded (byte string): A complete INTEGER DER element. - - Raises: - ValueError: in case of parsing errors. - """ - - return DerObject.decode(self, der_encoded, strict=strict) - - def _decodeFromStream(self, s, strict): - """Decode a complete DER INTEGER from a file.""" - - # Fill up self.payload - DerObject._decodeFromStream(self, s, strict) - - if strict: - if len(self.payload) == 0: - raise ValueError("Invalid encoding for DER INTEGER: empty payload") - if len(self.payload) >= 2 and struct.unpack('>H', self.payload[:2])[0] < 0x80: - raise ValueError("Invalid encoding for DER INTEGER: leading zero") - - # Derive self.value from self.payload - self.value = 0 - bits = 1 - for i in self.payload: - self.value *= 256 - self.value += bord(i) - bits <<= 8 - if self.payload and bord(self.payload[0]) & 0x80: - self.value -= bits - - -class DerSequence(DerObject): - """Class to model a DER SEQUENCE. - - This object behaves like a dynamic Python sequence. - - Sub-elements that are INTEGERs behave like Python integers. - - Any other sub-element is a binary string encoded as a complete DER - sub-element (TLV). - - An example of encoding is: - - >>> from Crypto.Util.asn1 import DerSequence, DerInteger - >>> from binascii import hexlify, unhexlify - >>> obj_der = unhexlify('070102') - >>> seq_der = DerSequence([4]) - >>> seq_der.append(9) - >>> seq_der.append(obj_der.encode()) - >>> print hexlify(seq_der.encode()) - - which will show ``3009020104020109070102``, the DER encoding of the - sequence containing ``4``, ``9``, and the object with payload ``02``. - - For decoding: - - >>> s = unhexlify(b'3009020104020109070102') - >>> try: - >>> seq_der = DerSequence() - >>> seq_der.decode(s) - >>> print len(seq_der) - >>> print seq_der[0] - >>> print seq_der[:] - >>> except ValueError: - >>> print "Not a valid DER SEQUENCE" - - the output will be:: - - 3 - 4 - [4, 9, b'\x07\x01\x02'] - - """ - - def __init__(self, startSeq=None, implicit=None): - """Initialize the DER object as a SEQUENCE. - - :Parameters: - startSeq : Python sequence - A sequence whose element are either integers or - other DER objects. - - implicit : integer - The IMPLICIT tag to use for the encoded object. - It overrides the universal tag for SEQUENCE (16). - """ - - DerObject.__init__(self, 0x10, b'', implicit, True) - if startSeq is None: - self._seq = [] - else: - self._seq = startSeq - - # A few methods to make it behave like a python sequence - - def __delitem__(self, n): - del self._seq[n] - - def __getitem__(self, n): - return self._seq[n] - - def __setitem__(self, key, value): - self._seq[key] = value - - def __setslice__(self, i, j, sequence): - self._seq[i:j] = sequence - - def __delslice__(self, i, j): - del self._seq[i:j] - - def __getslice__(self, i, j): - return self._seq[max(0, i):max(0, j)] - - def __len__(self): - return len(self._seq) - - def __iadd__(self, item): - self._seq.append(item) - return self - - def append(self, item): - self._seq.append(item) - return self - - def hasInts(self, only_non_negative=True): - """Return the number of items in this sequence that are - integers. - - Args: - only_non_negative (boolean): - If ``True``, negative integers are not counted in. - """ - - items = [x for x in self._seq if _is_number(x, only_non_negative)] - return len(items) - - def hasOnlyInts(self, only_non_negative=True): - """Return ``True`` if all items in this sequence are integers - or non-negative integers. - - This function returns False is the sequence is empty, - or at least one member is not an integer. - - Args: - only_non_negative (boolean): - If ``True``, the presence of negative integers - causes the method to return ``False``.""" - return self._seq and self.hasInts(only_non_negative) == len(self._seq) - - def encode(self): - """Return this DER SEQUENCE, fully encoded as a - binary string. - - Raises: - ValueError: if some elements in the sequence are neither integers - nor byte strings. - """ - self.payload = b'' - for item in self._seq: - if byte_string(item): - self.payload += item - elif _is_number(item): - self.payload += DerInteger(item).encode() - else: - self.payload += item.encode() - return DerObject.encode(self) - - def decode(self, der_encoded, strict=False, nr_elements=None, only_ints_expected=False): - """Decode a complete DER SEQUENCE, and re-initializes this - object with it. - - Args: - der_encoded (byte string): - A complete SEQUENCE DER element. - nr_elements (None or integer or list of integers): - The number of members the SEQUENCE can have - only_ints_expected (boolean): - Whether the SEQUENCE is expected to contain only integers. - strict (boolean): - Whether decoding must check for strict DER compliancy. - - Raises: - ValueError: in case of parsing errors. - - DER INTEGERs are decoded into Python integers. Any other DER - element is not decoded. Its validity is not checked. - """ - - self._nr_elements = nr_elements - result = DerObject.decode(self, der_encoded, strict=strict) - - if only_ints_expected and not self.hasOnlyInts(): - raise ValueError("Some members are not INTEGERs") - - return result - - def _decodeFromStream(self, s, strict): - """Decode a complete DER SEQUENCE from a file.""" - - self._seq = [] - - # Fill up self.payload - DerObject._decodeFromStream(self, s, strict) - - # Add one item at a time to self.seq, by scanning self.payload - p = BytesIO_EOF(self.payload) - while p.remaining_data() > 0: - p.set_bookmark() - - der = DerObject() - der._decodeFromStream(p, strict) - - # Parse INTEGERs differently - if der._tag_octet != 0x02: - self._seq.append(p.data_since_bookmark()) - else: - derInt = DerInteger() - #import pdb; pdb.set_trace() - data = p.data_since_bookmark() - derInt.decode(data, strict=strict) - self._seq.append(derInt.value) - - ok = True - if self._nr_elements is not None: - try: - ok = len(self._seq) in self._nr_elements - except TypeError: - ok = len(self._seq) == self._nr_elements - - if not ok: - raise ValueError("Unexpected number of members (%d)" - " in the sequence" % len(self._seq)) - - -class DerOctetString(DerObject): - """Class to model a DER OCTET STRING. - - An example of encoding is: - - >>> from Crypto.Util.asn1 import DerOctetString - >>> from binascii import hexlify, unhexlify - >>> os_der = DerOctetString(b'\\xaa') - >>> os_der.payload += b'\\xbb' - >>> print hexlify(os_der.encode()) - - which will show ``0402aabb``, the DER encoding for the byte string - ``b'\\xAA\\xBB'``. - - For decoding: - - >>> s = unhexlify(b'0402aabb') - >>> try: - >>> os_der = DerOctetString() - >>> os_der.decode(s) - >>> print hexlify(os_der.payload) - >>> except ValueError: - >>> print "Not a valid DER OCTET STRING" - - the output will be ``aabb``. - - :ivar payload: The content of the string - :vartype payload: byte string - """ - - def __init__(self, value=b'', implicit=None): - """Initialize the DER object as an OCTET STRING. - - :Parameters: - value : byte string - The initial payload of the object. - If not specified, the payload is empty. - - implicit : integer - The IMPLICIT tag to use for the encoded object. - It overrides the universal tag for OCTET STRING (4). - """ - DerObject.__init__(self, 0x04, value, implicit, False) - - -class DerNull(DerObject): - """Class to model a DER NULL element.""" - - def __init__(self): - """Initialize the DER object as a NULL.""" - - DerObject.__init__(self, 0x05, b'', None, False) - - -class DerObjectId(DerObject): - """Class to model a DER OBJECT ID. - - An example of encoding is: - - >>> from Crypto.Util.asn1 import DerObjectId - >>> from binascii import hexlify, unhexlify - >>> oid_der = DerObjectId("1.2") - >>> oid_der.value += ".840.113549.1.1.1" - >>> print hexlify(oid_der.encode()) - - which will show ``06092a864886f70d010101``, the DER encoding for the - RSA Object Identifier ``1.2.840.113549.1.1.1``. - - For decoding: - - >>> s = unhexlify(b'06092a864886f70d010101') - >>> try: - >>> oid_der = DerObjectId() - >>> oid_der.decode(s) - >>> print oid_der.value - >>> except ValueError: - >>> print "Not a valid DER OBJECT ID" - - the output will be ``1.2.840.113549.1.1.1``. - - :ivar value: The Object ID (OID), a dot separated list of integers - :vartype value: string - """ - - def __init__(self, value='', implicit=None, explicit=None): - """Initialize the DER object as an OBJECT ID. - - :Parameters: - value : string - The initial Object Identifier (e.g. "1.2.0.0.6.2"). - implicit : integer - The IMPLICIT tag to use for the encoded object. - It overrides the universal tag for OBJECT ID (6). - explicit : integer - The EXPLICIT tag to use for the encoded object. - """ - DerObject.__init__(self, 0x06, b'', implicit, False, explicit) - self.value = value - - def encode(self): - """Return the DER OBJECT ID, fully encoded as a - binary string.""" - - comps = [int(x) for x in self.value.split(".")] - if len(comps) < 2: - raise ValueError("Not a valid Object Identifier string") - self.payload = bchr(40*comps[0]+comps[1]) - for v in comps[2:]: - if v == 0: - enc = [0] - else: - enc = [] - while v: - enc.insert(0, (v & 0x7F) | 0x80) - v >>= 7 - enc[-1] &= 0x7F - self.payload += b''.join([bchr(x) for x in enc]) - return DerObject.encode(self) - - def decode(self, der_encoded, strict=False): - """Decode a complete DER OBJECT ID, and re-initializes this - object with it. - - Args: - der_encoded (byte string): - A complete DER OBJECT ID. - strict (boolean): - Whether decoding must check for strict DER compliancy. - - Raises: - ValueError: in case of parsing errors. - """ - - return DerObject.decode(self, der_encoded, strict) - - def _decodeFromStream(self, s, strict): - """Decode a complete DER OBJECT ID from a file.""" - - # Fill up self.payload - DerObject._decodeFromStream(self, s, strict) - - # Derive self.value from self.payload - p = BytesIO_EOF(self.payload) - comps = [str(x) for x in divmod(p.read_byte(), 40)] - v = 0 - while p.remaining_data(): - c = p.read_byte() - v = v*128 + (c & 0x7F) - if not (c & 0x80): - comps.append(str(v)) - v = 0 - self.value = '.'.join(comps) - - -class DerBitString(DerObject): - """Class to model a DER BIT STRING. - - An example of encoding is: - - >>> from Crypto.Util.asn1 import DerBitString - >>> from binascii import hexlify, unhexlify - >>> bs_der = DerBitString(b'\\xaa') - >>> bs_der.value += b'\\xbb' - >>> print hexlify(bs_der.encode()) - - which will show ``040300aabb``, the DER encoding for the bit string - ``b'\\xAA\\xBB'``. - - For decoding: - - >>> s = unhexlify(b'040300aabb') - >>> try: - >>> bs_der = DerBitString() - >>> bs_der.decode(s) - >>> print hexlify(bs_der.value) - >>> except ValueError: - >>> print "Not a valid DER BIT STRING" - - the output will be ``aabb``. - - :ivar value: The content of the string - :vartype value: byte string - """ - - def __init__(self, value=b'', implicit=None, explicit=None): - """Initialize the DER object as a BIT STRING. - - :Parameters: - value : byte string or DER object - The initial, packed bit string. - If not specified, the bit string is empty. - implicit : integer - The IMPLICIT tag to use for the encoded object. - It overrides the universal tag for OCTET STRING (3). - explicit : integer - The EXPLICIT tag to use for the encoded object. - """ - DerObject.__init__(self, 0x03, b'', implicit, False, explicit) - - # The bitstring value (packed) - if isinstance(value, DerObject): - self.value = value.encode() - else: - self.value = value - - def encode(self): - """Return the DER BIT STRING, fully encoded as a - binary string.""" - - # Add padding count byte - self.payload = b'\x00' + self.value - return DerObject.encode(self) - - def decode(self, der_encoded, strict=False): - """Decode a complete DER BIT STRING, and re-initializes this - object with it. - - Args: - der_encoded (byte string): a complete DER BIT STRING. - strict (boolean): - Whether decoding must check for strict DER compliancy. - - Raises: - ValueError: in case of parsing errors. - """ - - return DerObject.decode(self, der_encoded, strict) - - def _decodeFromStream(self, s, strict): - """Decode a complete DER BIT STRING DER from a file.""" - - # Fill-up self.payload - DerObject._decodeFromStream(self, s, strict) - - if self.payload and bord(self.payload[0]) != 0: - raise ValueError("Not a valid BIT STRING") - - # Fill-up self.value - self.value = b'' - # Remove padding count byte - if self.payload: - self.value = self.payload[1:] - - -class DerSetOf(DerObject): - """Class to model a DER SET OF. - - An example of encoding is: - - >>> from Crypto.Util.asn1 import DerBitString - >>> from binascii import hexlify, unhexlify - >>> so_der = DerSetOf([4,5]) - >>> so_der.add(6) - >>> print hexlify(so_der.encode()) - - which will show ``3109020104020105020106``, the DER encoding - of a SET OF with items 4,5, and 6. - - For decoding: - - >>> s = unhexlify(b'3109020104020105020106') - >>> try: - >>> so_der = DerSetOf() - >>> so_der.decode(s) - >>> print [x for x in so_der] - >>> except ValueError: - >>> print "Not a valid DER SET OF" - - the output will be ``[4, 5, 6]``. - """ - - def __init__(self, startSet=None, implicit=None): - """Initialize the DER object as a SET OF. - - :Parameters: - startSet : container - The initial set of integers or DER encoded objects. - implicit : integer - The IMPLICIT tag to use for the encoded object. - It overrides the universal tag for SET OF (17). - """ - DerObject.__init__(self, 0x11, b'', implicit, True) - self._seq = [] - - # All elements must be of the same type (and therefore have the - # same leading octet) - self._elemOctet = None - - if startSet: - for e in startSet: - self.add(e) - - def __getitem__(self, n): - return self._seq[n] - - def __iter__(self): - return iter(self._seq) - - def __len__(self): - return len(self._seq) - - def add(self, elem): - """Add an element to the set. - - Args: - elem (byte string or integer): - An element of the same type of objects already in the set. - It can be an integer or a DER encoded object. - """ - - if _is_number(elem): - eo = 0x02 - elif isinstance(elem, DerObject): - eo = self._tag_octet - else: - eo = bord(elem[0]) - - if self._elemOctet != eo: - if self._elemOctet is not None: - raise ValueError("New element does not belong to the set") - self._elemOctet = eo - - if elem not in self._seq: - self._seq.append(elem) - - def decode(self, der_encoded, strict=False): - """Decode a complete SET OF DER element, and re-initializes this - object with it. - - DER INTEGERs are decoded into Python integers. Any other DER - element is left undecoded; its validity is not checked. - - Args: - der_encoded (byte string): a complete DER BIT SET OF. - strict (boolean): - Whether decoding must check for strict DER compliancy. - - Raises: - ValueError: in case of parsing errors. - """ - - return DerObject.decode(self, der_encoded, strict) - - def _decodeFromStream(self, s, strict): - """Decode a complete DER SET OF from a file.""" - - self._seq = [] - - # Fill up self.payload - DerObject._decodeFromStream(self, s, strict) - - # Add one item at a time to self.seq, by scanning self.payload - p = BytesIO_EOF(self.payload) - setIdOctet = -1 - while p.remaining_data() > 0: - p.set_bookmark() - - der = DerObject() - der._decodeFromStream(p, strict) - - # Verify that all members are of the same type - if setIdOctet < 0: - setIdOctet = der._tag_octet - else: - if setIdOctet != der._tag_octet: - raise ValueError("Not all elements are of the same DER type") - - # Parse INTEGERs differently - if setIdOctet != 0x02: - self._seq.append(p.data_since_bookmark()) - else: - derInt = DerInteger() - derInt.decode(p.data_since_bookmark(), strict) - self._seq.append(derInt.value) - # end - - def encode(self): - """Return this SET OF DER element, fully encoded as a - binary string. - """ - - # Elements in the set must be ordered in lexicographic order - ordered = [] - for item in self._seq: - if _is_number(item): - bys = DerInteger(item).encode() - elif isinstance(item, DerObject): - bys = item.encode() - else: - bys = item - ordered.append(bys) - ordered.sort() - self.payload = b''.join(ordered) - return DerObject.encode(self) diff --git a/Crypto/Util/asn1.pyi b/Crypto/Util/asn1.pyi deleted file mode 100644 index dac023b..0000000 --- a/Crypto/Util/asn1.pyi +++ /dev/null @@ -1,74 +0,0 @@ -from typing import Optional, Sequence, Union, Set, Iterable - -__all__ = ['DerObject', 'DerInteger', 'DerOctetString', 'DerNull', - 'DerSequence', 'DerObjectId', 'DerBitString', 'DerSetOf'] - -# TODO: Make the encoded DerObjects their own type, so that DerSequence and -# DerSetOf can check their contents better - -class BytesIO_EOF: - def __init__(self, initial_bytes: bytes) -> None: ... - def set_bookmark(self) -> None: ... - def data_since_bookmark(self) -> bytes: ... - def remaining_data(self) -> int: ... - def read(self, length: int) -> bytes: ... - def read_byte(self) -> bytes: ... - -class DerObject: - payload: bytes - def __init__(self, asn1Id: Optional[int]=None, payload: Optional[bytes]=..., implicit: Optional[int]=None, - constructed: Optional[bool]=False, explicit: Optional[int]=None) -> None: ... - def encode(self) -> bytes: ... - def decode(self, der_encoded: bytes, strict: Optional[bool]=False) -> DerObject: ... - -class DerInteger(DerObject): - value: int - def __init__(self, value: Optional[int]= 0, implicit: Optional[int]=None, explicit: Optional[int]=None) -> None: ... - def encode(self) -> bytes: ... - def decode(self, der_encoded: bytes, strict: Optional[bool]=False) -> DerInteger: ... - -class DerSequence(DerObject): - def __init__(self, startSeq: Optional[Sequence[Union[int, DerInteger, DerObject]]]=None, implicit: Optional[int]=None) -> None: ... - def __delitem__(self, n: int) -> None: ... - def __getitem__(self, n: int) -> None: ... - def __setitem__(self, key: int, value: DerObject) -> None: ... - def __setslice__(self, i: int, j: int, sequence: Sequence) -> None: ... - def __delslice__(self, i: int, j: int) -> None: ... - def __getslice__(self, i: int, j: int) -> DerSequence: ... - def __len__(self) -> int: ... - def __iadd__(self, item: DerObject) -> DerSequence: ... - def append(self, item: DerObject) -> DerSequence: ... - def hasInts(self, only_non_negative: Optional[bool]=True) -> int: ... - def hasOnlyInts(self, only_non_negative: Optional[bool]=True) -> bool: ... - def encode(self) -> bytes: ... - def decode(self, der_encoded: bytes, strict: Optional[bool]=False, nr_elements: Optional[int]=None, only_ints_expected: Optional[bool]=False) -> DerSequence: ... - -class DerOctetString(DerObject): - payload: bytes - def __init__(self, value: Optional[bytes]=..., implicit: Optional[int]=None) -> None: ... - -class DerNull(DerObject): - def __init__(self) -> None: ... - -class DerObjectId(DerObject): - value: str - def __init__(self, value: Optional[str]=..., implicit: Optional[int]=None, explicit: Optional[int]=None) -> None: ... - def encode(self) -> bytes: ... - def decode(self, der_encoded: bytes, strict: Optional[bool]=False) -> DerObjectId: ... - -class DerBitString(DerObject): - value: bytes - def __init__(self, value: Optional[bytes]=..., implicit: Optional[int]=None, explicit: Optional[int]=None) -> None: ... - def encode(self) -> bytes: ... - def decode(self, der_encoded: bytes, strict: Optional[bool]=False) -> DerBitString: ... - -DerSetElement = Union[bytes, int] - -class DerSetOf(DerObject): - def __init__(self, startSet: Optional[Set[DerSetElement]]=None, implicit: Optional[int]=None) -> None: ... - def __getitem__(self, n: int) -> DerSetElement: ... - def __iter__(self) -> Iterable: ... - def __len__(self) -> int: ... - def add(self, elem: DerSetElement) -> None: ... - def decode(self, der_encoded: bytes, strict: Optional[bool]=False) -> DerObject: ... - def encode(self) -> bytes: ... diff --git a/Crypto/Util/number.py b/Crypto/Util/number.py deleted file mode 100644 index 56df021..0000000 --- a/Crypto/Util/number.py +++ /dev/null @@ -1,1469 +0,0 @@ -# -# number.py : Number-theoretic functions -# -# Part of the Python Cryptography Toolkit -# -# Written by Andrew M. Kuchling, Barry A. Warsaw, and others -# -# =================================================================== -# The contents of this file are dedicated to the public domain. To -# the extent that dedication to the public domain is not available, -# everyone is granted a worldwide, perpetual, royalty-free, -# non-exclusive license to exercise all rights associated with the -# contents of this file for any purpose whatsoever. -# No rights are reserved. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# =================================================================== -# - -import math -import sys -import struct -from Crypto import Random -from Crypto.Util.py3compat import iter_range - -# Backward compatibility -_fastmath = None - - -def ceil_div(n, d): - """Return ceil(n/d), that is, the smallest integer r such that r*d >= n""" - - if d == 0: - raise ZeroDivisionError() - if (n < 0) or (d < 0): - raise ValueError("Non positive values") - r, q = divmod(n, d) - if (n != 0) and (q != 0): - r += 1 - return r - - -def size (N): - """Returns the size of the number N in bits.""" - - if N < 0: - raise ValueError("Size in bits only avialable for non-negative numbers") - - bits = 0 - while N >> bits: - bits += 1 - return bits - - -def getRandomInteger(N, randfunc=None): - """Return a random number at most N bits long. - - If :data:`randfunc` is omitted, then :meth:`Random.get_random_bytes` is used. - - .. deprecated:: 3.0 - This function is for internal use only and may be renamed or removed in - the future. Use :func:`Crypto.Random.random.getrandbits` instead. - """ - - if randfunc is None: - randfunc = Random.get_random_bytes - - S = randfunc(N>>3) - odd_bits = N % 8 - if odd_bits != 0: - rand_bits = ord(randfunc(1)) >> (8-odd_bits) - S = struct.pack('B', rand_bits) + S - value = bytes_to_long(S) - return value - -def getRandomRange(a, b, randfunc=None): - """Return a random number *n* so that *a <= n < b*. - - If :data:`randfunc` is omitted, then :meth:`Random.get_random_bytes` is used. - - .. deprecated:: 3.0 - This function is for internal use only and may be renamed or removed in - the future. Use :func:`Crypto.Random.random.randrange` instead. - """ - - range_ = b - a - 1 - bits = size(range_) - value = getRandomInteger(bits, randfunc) - while value > range_: - value = getRandomInteger(bits, randfunc) - return a + value - -def getRandomNBitInteger(N, randfunc=None): - """Return a random number with exactly N-bits, - i.e. a random number between 2**(N-1) and (2**N)-1. - - If :data:`randfunc` is omitted, then :meth:`Random.get_random_bytes` is used. - - .. deprecated:: 3.0 - This function is for internal use only and may be renamed or removed in - the future. - """ - - value = getRandomInteger (N-1, randfunc) - value |= 2 ** (N-1) # Ensure high bit is set - assert size(value) >= N - return value - -def GCD(x,y): - """Greatest Common Denominator of :data:`x` and :data:`y`. - """ - - x = abs(x) ; y = abs(y) - while x > 0: - x, y = y % x, x - return y - -def inverse(u, v): - """The inverse of :data:`u` *mod* :data:`v`.""" - - u3, v3 = u, v - u1, v1 = 1, 0 - while v3 > 0: - q = u3 // v3 - u1, v1 = v1, u1 - v1*q - u3, v3 = v3, u3 - v3*q - while u1<0: - u1 = u1 + v - return u1 - -# Given a number of bits to generate and a random generation function, -# find a prime number of the appropriate size. - -def getPrime(N, randfunc=None): - """Return a random N-bit prime number. - - If randfunc is omitted, then :meth:`Random.get_random_bytes` is used. - """ - if randfunc is None: - randfunc = Random.get_random_bytes - - number=getRandomNBitInteger(N, randfunc) | 1 - while (not isPrime(number, randfunc=randfunc)): - number=number+2 - return number - - -def _rabinMillerTest(n, rounds, randfunc=None): - """_rabinMillerTest(n:long, rounds:int, randfunc:callable):int - Tests if n is prime. - Returns 0 when n is definitely composite. - Returns 1 when n is probably prime. - Returns 2 when n is definitely prime. - - If randfunc is omitted, then Random.new().read is used. - - This function is for internal use only and may be renamed or removed in - the future. - """ - # check special cases (n==2, n even, n < 2) - if n < 3 or (n & 1) == 0: - return n == 2 - # n might be very large so it might be beneficial to precalculate n-1 - n_1 = n - 1 - # determine m and b so that 2**b * m = n - 1 and b maximal - b = 0 - m = n_1 - while (m & 1) == 0: - b += 1 - m >>= 1 - - tested = [] - # we need to do at most n-2 rounds. - for i in iter_range (min (rounds, n-2)): - # randomly choose a < n and make sure it hasn't been tested yet - a = getRandomRange (2, n, randfunc) - while a in tested: - a = getRandomRange (2, n, randfunc) - tested.append (a) - # do the rabin-miller test - z = pow (a, m, n) # (a**m) % n - if z == 1 or z == n_1: - continue - composite = 1 - for r in iter_range(b): - z = (z * z) % n - if z == 1: - return 0 - elif z == n_1: - composite = 0 - break - if composite: - return 0 - return 1 - -def getStrongPrime(N, e=0, false_positive_prob=1e-6, randfunc=None): - r""" - Return a random strong *N*-bit prime number. - In this context, *p* is a strong prime if *p-1* and *p+1* have at - least one large prime factor. - - Args: - N (integer): the exact length of the strong prime. - It must be a multiple of 128 and > 512. - e (integer): if provided, the returned prime (minus 1) - will be coprime to *e* and thus suitable for RSA where - *e* is the public exponent. - false_positive_prob (float): - The statistical probability for the result not to be actually a - prime. It defaults to 10\ :sup:`-6`. - Note that the real probability of a false-positive is far less. This is - just the mathematically provable limit. - randfunc (callable): - A function that takes a parameter *N* and that returns - a random byte string of such length. - If omitted, :func:`Crypto.Random.get_random_bytes` is used. - Return: - The new strong prime. - - .. deprecated:: 3.0 - This function is for internal use only and may be renamed or removed in - the future. - """ - - # This function was implemented following the - # instructions found in the paper: - # "FAST GENERATION OF RANDOM, STRONG RSA PRIMES" - # by Robert D. Silverman - # RSA Laboratories - # May 17, 1997 - # which by the time of writing could be freely downloaded here: - # http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.17.2713&rep=rep1&type=pdf - - if randfunc is None: - randfunc = Random.get_random_bytes - - # Use the accelerator if available - if _fastmath is not None: - return _fastmath.getStrongPrime(long(N), long(e), false_positive_prob, - randfunc) - - if (N < 512) or ((N % 128) != 0): - raise ValueError ("bits must be multiple of 128 and > 512") - - rabin_miller_rounds = int(math.ceil(-math.log(false_positive_prob)/math.log(4))) - - # calculate range for X - # lower_bound = sqrt(2) * 2^{511 + 128*x} - # upper_bound = 2^{512 + 128*x} - 1 - x = (N - 512) >> 7; - # We need to approximate the sqrt(2) in the lower_bound by an integer - # expression because floating point math overflows with these numbers - lower_bound = (14142135623730950489 * (2 ** (511 + 128*x))) // 10000000000000000000 - upper_bound = (1 << (512 + 128*x)) - 1 - # Randomly choose X in calculated range - X = getRandomRange (lower_bound, upper_bound, randfunc) - - # generate p1 and p2 - p = [0, 0] - for i in (0, 1): - # randomly choose 101-bit y - y = getRandomNBitInteger (101, randfunc) - # initialize the field for sieving - field = [0] * 5 * len (sieve_base) - # sieve the field - for prime in sieve_base: - offset = y % prime - for j in iter_range((prime - offset) % prime, len (field), prime): - field[j] = 1 - - # look for suitable p[i] starting at y - result = 0 - for j in range(len(field)): - composite = field[j] - # look for next canidate - if composite: - continue - tmp = y + j - result = _rabinMillerTest (tmp, rabin_miller_rounds) - if result > 0: - p[i] = tmp - break - if result == 0: - raise RuntimeError ("Couln't find prime in field. " - "Developer: Increase field_size") - - # Calculate R - # R = (p2^{-1} mod p1) * p2 - (p1^{-1} mod p2) * p1 - tmp1 = inverse (p[1], p[0]) * p[1] # (p2^-1 mod p1)*p2 - tmp2 = inverse (p[0], p[1]) * p[0] # (p1^-1 mod p2)*p1 - R = tmp1 - tmp2 # (p2^-1 mod p1)*p2 - (p1^-1 mod p2)*p1 - - # search for final prime number starting by Y0 - # Y0 = X + (R - X mod p1p2) - increment = p[0] * p[1] - X = X + (R - (X % increment)) - while 1: - is_possible_prime = 1 - # first check candidate against sieve_base - for prime in sieve_base: - if (X % prime) == 0: - is_possible_prime = 0 - break - # if e is given make sure that e and X-1 are coprime - # this is not necessarily a strong prime criterion but useful when - # creating them for RSA where the p-1 and q-1 should be coprime to - # the public exponent e - if e and is_possible_prime: - if e & 1: - if GCD(e, X-1) != 1: - is_possible_prime = 0 - else: - if GCD(e, (X-1) // 2) != 1: - is_possible_prime = 0 - - # do some Rabin-Miller-Tests - if is_possible_prime: - result = _rabinMillerTest (X, rabin_miller_rounds) - if result > 0: - break - X += increment - # abort when X has more bits than requested - # TODO: maybe we shouldn't abort but rather start over. - if X >= 1 << N: - raise RuntimeError ("Couln't find prime in field. " - "Developer: Increase field_size") - return X - -def isPrime(N, false_positive_prob=1e-6, randfunc=None): - r"""Test if a number *N* is a prime. - - Args: - false_positive_prob (float): - The statistical probability for the result not to be actually a - prime. It defaults to 10\ :sup:`-6`. - Note that the real probability of a false-positive is far less. - This is just the mathematically provable limit. - randfunc (callable): - A function that takes a parameter *N* and that returns - a random byte string of such length. - If omitted, :func:`Crypto.Random.get_random_bytes` is used. - - Return: - `True` is the input is indeed prime. - """ - - if randfunc is None: - randfunc = Random.get_random_bytes - - if _fastmath is not None: - return _fastmath.isPrime(long(N), false_positive_prob, randfunc) - - if N < 3 or N & 1 == 0: - return N == 2 - for p in sieve_base: - if N == p: - return 1 - if N % p == 0: - return 0 - - rounds = int(math.ceil(-math.log(false_positive_prob)/math.log(4))) - return _rabinMillerTest(N, rounds, randfunc) - - -# Improved conversion functions contributed by Barry Warsaw, after -# careful benchmarking - -import struct - -def long_to_bytes(n, blocksize=0): - """Convert an integer to a byte string. - - In Python 3.2+, use the native method instead:: - - >>> n.to_bytes(blocksize, 'big') - - For instance:: - - >>> n = 80 - >>> n.to_bytes(2, 'big') - b'\x00P' - - If the optional :data:`blocksize` is provided and greater than zero, - the byte string is padded with binary zeros (on the front) so that - the total length of the output is a multiple of blocksize. - - If :data:`blocksize` is zero or not provided, the byte string will - be of minimal length. - """ - # after much testing, this algorithm was deemed to be the fastest - s = b'' - n = int(n) - pack = struct.pack - while n > 0: - s = pack('>I', n & 0xffffffff) + s - n = n >> 32 - # strip off leading zeros - for i in range(len(s)): - if s[i] != b'\x00'[0]: - break - else: - # only happens when n == 0 - s = b'\x00' - i = 0 - s = s[i:] - # add back some pad bytes. this could be done more efficiently w.r.t. the - # de-padding being done above, but sigh... - if blocksize > 0 and len(s) % blocksize: - s = (blocksize - len(s) % blocksize) * b'\x00' + s - return s - -def bytes_to_long(s): - """Convert a byte string to a long integer (big endian). - - In Python 3.2+, use the native method instead:: - - >>> int.from_bytes(s, 'big') - - For instance:: - - >>> int.from_bytes(b'\x00P', 'big') - 80 - - This is (essentially) the inverse of :func:`long_to_bytes`. - """ - acc = 0 - - unpack = struct.unpack - - # Up to Python 2.7.4, struct.unpack can't work with bytearrays nor - # memoryviews - if sys.version_info[0:3] < (2, 7, 4): - if isinstance(s, bytearray): - s = bytes(s) - elif isinstance(s, memoryview): - s = s.tobytes() - - length = len(s) - if length % 4: - extra = (4 - length % 4) - s = b'\x00' * extra + s - length = length + extra - for i in range(0, length, 4): - acc = (acc << 32) + unpack('>I', s[i:i+4])[0] - return acc - - -# For backwards compatibility... -import warnings -def long2str(n, blocksize=0): - warnings.warn("long2str() has been replaced by long_to_bytes()") - return long_to_bytes(n, blocksize) -def str2long(s): - warnings.warn("str2long() has been replaced by bytes_to_long()") - return bytes_to_long(s) - - -# The first 10000 primes used for checking primality. -# This should be enough to eliminate most of the odd -# numbers before needing to do a Rabin-Miller test at all. -sieve_base = ( - 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, - 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, - 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, - 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, - 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, - 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, - 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, - 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, - 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, - 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, - 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, - 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, - 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, - 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, - 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, - 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, - 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, - 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, - 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, - 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, - 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, - 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, - 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, - 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, - 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, - 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, - 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, - 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, - 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, - 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, - 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, - 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, - 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, - 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, - 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, - 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, - 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, - 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, - 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, - 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, - 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, - 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, - 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, - 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, - 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, - 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, - 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, - 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, - 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, - 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, - 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, - 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, - 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, - 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, - 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, - 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, - 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, - 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, - 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, - 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, - 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, - 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, - 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, - 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, - 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, - 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, - 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, - 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, - 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, - 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, - 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, - 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, - 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, - 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, - 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, - 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, - 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, - 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, - 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, - 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, - 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, - 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, - 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, - 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, - 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, - 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, - 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, - 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, - 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, - 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, - 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, - 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, - 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, - 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, - 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, - 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, - 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, - 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, - 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, - 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, - 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017, - 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, - 8117, 8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209, 8219, - 8221, 8231, 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291, - 8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, 8377, 8387, - 8389, 8419, 8423, 8429, 8431, 8443, 8447, 8461, 8467, 8501, - 8513, 8521, 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597, - 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677, - 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741, - 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831, - 8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929, - 8933, 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011, - 9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109, - 9127, 9133, 9137, 9151, 9157, 9161, 9173, 9181, 9187, 9199, - 9203, 9209, 9221, 9227, 9239, 9241, 9257, 9277, 9281, 9283, - 9293, 9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377, - 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439, - 9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521, 9533, - 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629, 9631, - 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733, - 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811, - 9817, 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887, - 9901, 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973, 10007, - 10009, 10037, 10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099, - 10103, 10111, 10133, 10139, 10141, 10151, 10159, 10163, 10169, 10177, - 10181, 10193, 10211, 10223, 10243, 10247, 10253, 10259, 10267, 10271, - 10273, 10289, 10301, 10303, 10313, 10321, 10331, 10333, 10337, 10343, - 10357, 10369, 10391, 10399, 10427, 10429, 10433, 10453, 10457, 10459, - 10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531, 10559, 10567, - 10589, 10597, 10601, 10607, 10613, 10627, 10631, 10639, 10651, 10657, - 10663, 10667, 10687, 10691, 10709, 10711, 10723, 10729, 10733, 10739, - 10753, 10771, 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859, - 10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937, 10939, 10949, - 10957, 10973, 10979, 10987, 10993, 11003, 11027, 11047, 11057, 11059, - 11069, 11071, 11083, 11087, 11093, 11113, 11117, 11119, 11131, 11149, - 11159, 11161, 11171, 11173, 11177, 11197, 11213, 11239, 11243, 11251, - 11257, 11261, 11273, 11279, 11287, 11299, 11311, 11317, 11321, 11329, - 11351, 11353, 11369, 11383, 11393, 11399, 11411, 11423, 11437, 11443, - 11447, 11467, 11471, 11483, 11489, 11491, 11497, 11503, 11519, 11527, - 11549, 11551, 11579, 11587, 11593, 11597, 11617, 11621, 11633, 11657, - 11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731, 11743, 11777, - 11779, 11783, 11789, 11801, 11807, 11813, 11821, 11827, 11831, 11833, - 11839, 11863, 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933, - 11939, 11941, 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011, - 12037, 12041, 12043, 12049, 12071, 12073, 12097, 12101, 12107, 12109, - 12113, 12119, 12143, 12149, 12157, 12161, 12163, 12197, 12203, 12211, - 12227, 12239, 12241, 12251, 12253, 12263, 12269, 12277, 12281, 12289, - 12301, 12323, 12329, 12343, 12347, 12373, 12377, 12379, 12391, 12401, - 12409, 12413, 12421, 12433, 12437, 12451, 12457, 12473, 12479, 12487, - 12491, 12497, 12503, 12511, 12517, 12527, 12539, 12541, 12547, 12553, - 12569, 12577, 12583, 12589, 12601, 12611, 12613, 12619, 12637, 12641, - 12647, 12653, 12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739, - 12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823, 12829, - 12841, 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919, 12923, - 12941, 12953, 12959, 12967, 12973, 12979, 12983, 13001, 13003, 13007, - 13009, 13033, 13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109, - 13121, 13127, 13147, 13151, 13159, 13163, 13171, 13177, 13183, 13187, - 13217, 13219, 13229, 13241, 13249, 13259, 13267, 13291, 13297, 13309, - 13313, 13327, 13331, 13337, 13339, 13367, 13381, 13397, 13399, 13411, - 13417, 13421, 13441, 13451, 13457, 13463, 13469, 13477, 13487, 13499, - 13513, 13523, 13537, 13553, 13567, 13577, 13591, 13597, 13613, 13619, - 13627, 13633, 13649, 13669, 13679, 13681, 13687, 13691, 13693, 13697, - 13709, 13711, 13721, 13723, 13729, 13751, 13757, 13759, 13763, 13781, - 13789, 13799, 13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879, - 13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, 13963, 13967, - 13997, 13999, 14009, 14011, 14029, 14033, 14051, 14057, 14071, 14081, - 14083, 14087, 14107, 14143, 14149, 14153, 14159, 14173, 14177, 14197, - 14207, 14221, 14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323, - 14327, 14341, 14347, 14369, 14387, 14389, 14401, 14407, 14411, 14419, - 14423, 14431, 14437, 14447, 14449, 14461, 14479, 14489, 14503, 14519, - 14533, 14537, 14543, 14549, 14551, 14557, 14561, 14563, 14591, 14593, - 14621, 14627, 14629, 14633, 14639, 14653, 14657, 14669, 14683, 14699, - 14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753, 14759, 14767, - 14771, 14779, 14783, 14797, 14813, 14821, 14827, 14831, 14843, 14851, - 14867, 14869, 14879, 14887, 14891, 14897, 14923, 14929, 14939, 14947, - 14951, 14957, 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073, - 15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137, 15139, 15149, - 15161, 15173, 15187, 15193, 15199, 15217, 15227, 15233, 15241, 15259, - 15263, 15269, 15271, 15277, 15287, 15289, 15299, 15307, 15313, 15319, - 15329, 15331, 15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401, - 15413, 15427, 15439, 15443, 15451, 15461, 15467, 15473, 15493, 15497, - 15511, 15527, 15541, 15551, 15559, 15569, 15581, 15583, 15601, 15607, - 15619, 15629, 15641, 15643, 15647, 15649, 15661, 15667, 15671, 15679, - 15683, 15727, 15731, 15733, 15737, 15739, 15749, 15761, 15767, 15773, - 15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859, 15877, 15881, - 15887, 15889, 15901, 15907, 15913, 15919, 15923, 15937, 15959, 15971, - 15973, 15991, 16001, 16007, 16033, 16057, 16061, 16063, 16067, 16069, - 16073, 16087, 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183, - 16187, 16189, 16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267, - 16273, 16301, 16319, 16333, 16339, 16349, 16361, 16363, 16369, 16381, - 16411, 16417, 16421, 16427, 16433, 16447, 16451, 16453, 16477, 16481, - 16487, 16493, 16519, 16529, 16547, 16553, 16561, 16567, 16573, 16603, - 16607, 16619, 16631, 16633, 16649, 16651, 16657, 16661, 16673, 16691, - 16693, 16699, 16703, 16729, 16741, 16747, 16759, 16763, 16787, 16811, - 16823, 16829, 16831, 16843, 16871, 16879, 16883, 16889, 16901, 16903, - 16921, 16927, 16931, 16937, 16943, 16963, 16979, 16981, 16987, 16993, - 17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053, 17077, 17093, - 17099, 17107, 17117, 17123, 17137, 17159, 17167, 17183, 17189, 17191, - 17203, 17207, 17209, 17231, 17239, 17257, 17291, 17293, 17299, 17317, - 17321, 17327, 17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389, - 17393, 17401, 17417, 17419, 17431, 17443, 17449, 17467, 17471, 17477, - 17483, 17489, 17491, 17497, 17509, 17519, 17539, 17551, 17569, 17573, - 17579, 17581, 17597, 17599, 17609, 17623, 17627, 17657, 17659, 17669, - 17681, 17683, 17707, 17713, 17729, 17737, 17747, 17749, 17761, 17783, - 17789, 17791, 17807, 17827, 17837, 17839, 17851, 17863, 17881, 17891, - 17903, 17909, 17911, 17921, 17923, 17929, 17939, 17957, 17959, 17971, - 17977, 17981, 17987, 17989, 18013, 18041, 18043, 18047, 18049, 18059, - 18061, 18077, 18089, 18097, 18119, 18121, 18127, 18131, 18133, 18143, - 18149, 18169, 18181, 18191, 18199, 18211, 18217, 18223, 18229, 18233, - 18251, 18253, 18257, 18269, 18287, 18289, 18301, 18307, 18311, 18313, - 18329, 18341, 18353, 18367, 18371, 18379, 18397, 18401, 18413, 18427, - 18433, 18439, 18443, 18451, 18457, 18461, 18481, 18493, 18503, 18517, - 18521, 18523, 18539, 18541, 18553, 18583, 18587, 18593, 18617, 18637, - 18661, 18671, 18679, 18691, 18701, 18713, 18719, 18731, 18743, 18749, - 18757, 18773, 18787, 18793, 18797, 18803, 18839, 18859, 18869, 18899, - 18911, 18913, 18917, 18919, 18947, 18959, 18973, 18979, 19001, 19009, - 19013, 19031, 19037, 19051, 19069, 19073, 19079, 19081, 19087, 19121, - 19139, 19141, 19157, 19163, 19181, 19183, 19207, 19211, 19213, 19219, - 19231, 19237, 19249, 19259, 19267, 19273, 19289, 19301, 19309, 19319, - 19333, 19373, 19379, 19381, 19387, 19391, 19403, 19417, 19421, 19423, - 19427, 19429, 19433, 19441, 19447, 19457, 19463, 19469, 19471, 19477, - 19483, 19489, 19501, 19507, 19531, 19541, 19543, 19553, 19559, 19571, - 19577, 19583, 19597, 19603, 19609, 19661, 19681, 19687, 19697, 19699, - 19709, 19717, 19727, 19739, 19751, 19753, 19759, 19763, 19777, 19793, - 19801, 19813, 19819, 19841, 19843, 19853, 19861, 19867, 19889, 19891, - 19913, 19919, 19927, 19937, 19949, 19961, 19963, 19973, 19979, 19991, - 19993, 19997, 20011, 20021, 20023, 20029, 20047, 20051, 20063, 20071, - 20089, 20101, 20107, 20113, 20117, 20123, 20129, 20143, 20147, 20149, - 20161, 20173, 20177, 20183, 20201, 20219, 20231, 20233, 20249, 20261, - 20269, 20287, 20297, 20323, 20327, 20333, 20341, 20347, 20353, 20357, - 20359, 20369, 20389, 20393, 20399, 20407, 20411, 20431, 20441, 20443, - 20477, 20479, 20483, 20507, 20509, 20521, 20533, 20543, 20549, 20551, - 20563, 20593, 20599, 20611, 20627, 20639, 20641, 20663, 20681, 20693, - 20707, 20717, 20719, 20731, 20743, 20747, 20749, 20753, 20759, 20771, - 20773, 20789, 20807, 20809, 20849, 20857, 20873, 20879, 20887, 20897, - 20899, 20903, 20921, 20929, 20939, 20947, 20959, 20963, 20981, 20983, - 21001, 21011, 21013, 21017, 21019, 21023, 21031, 21059, 21061, 21067, - 21089, 21101, 21107, 21121, 21139, 21143, 21149, 21157, 21163, 21169, - 21179, 21187, 21191, 21193, 21211, 21221, 21227, 21247, 21269, 21277, - 21283, 21313, 21317, 21319, 21323, 21341, 21347, 21377, 21379, 21383, - 21391, 21397, 21401, 21407, 21419, 21433, 21467, 21481, 21487, 21491, - 21493, 21499, 21503, 21517, 21521, 21523, 21529, 21557, 21559, 21563, - 21569, 21577, 21587, 21589, 21599, 21601, 21611, 21613, 21617, 21647, - 21649, 21661, 21673, 21683, 21701, 21713, 21727, 21737, 21739, 21751, - 21757, 21767, 21773, 21787, 21799, 21803, 21817, 21821, 21839, 21841, - 21851, 21859, 21863, 21871, 21881, 21893, 21911, 21929, 21937, 21943, - 21961, 21977, 21991, 21997, 22003, 22013, 22027, 22031, 22037, 22039, - 22051, 22063, 22067, 22073, 22079, 22091, 22093, 22109, 22111, 22123, - 22129, 22133, 22147, 22153, 22157, 22159, 22171, 22189, 22193, 22229, - 22247, 22259, 22271, 22273, 22277, 22279, 22283, 22291, 22303, 22307, - 22343, 22349, 22367, 22369, 22381, 22391, 22397, 22409, 22433, 22441, - 22447, 22453, 22469, 22481, 22483, 22501, 22511, 22531, 22541, 22543, - 22549, 22567, 22571, 22573, 22613, 22619, 22621, 22637, 22639, 22643, - 22651, 22669, 22679, 22691, 22697, 22699, 22709, 22717, 22721, 22727, - 22739, 22741, 22751, 22769, 22777, 22783, 22787, 22807, 22811, 22817, - 22853, 22859, 22861, 22871, 22877, 22901, 22907, 22921, 22937, 22943, - 22961, 22963, 22973, 22993, 23003, 23011, 23017, 23021, 23027, 23029, - 23039, 23041, 23053, 23057, 23059, 23063, 23071, 23081, 23087, 23099, - 23117, 23131, 23143, 23159, 23167, 23173, 23189, 23197, 23201, 23203, - 23209, 23227, 23251, 23269, 23279, 23291, 23293, 23297, 23311, 23321, - 23327, 23333, 23339, 23357, 23369, 23371, 23399, 23417, 23431, 23447, - 23459, 23473, 23497, 23509, 23531, 23537, 23539, 23549, 23557, 23561, - 23563, 23567, 23581, 23593, 23599, 23603, 23609, 23623, 23627, 23629, - 23633, 23663, 23669, 23671, 23677, 23687, 23689, 23719, 23741, 23743, - 23747, 23753, 23761, 23767, 23773, 23789, 23801, 23813, 23819, 23827, - 23831, 23833, 23857, 23869, 23873, 23879, 23887, 23893, 23899, 23909, - 23911, 23917, 23929, 23957, 23971, 23977, 23981, 23993, 24001, 24007, - 24019, 24023, 24029, 24043, 24049, 24061, 24071, 24077, 24083, 24091, - 24097, 24103, 24107, 24109, 24113, 24121, 24133, 24137, 24151, 24169, - 24179, 24181, 24197, 24203, 24223, 24229, 24239, 24247, 24251, 24281, - 24317, 24329, 24337, 24359, 24371, 24373, 24379, 24391, 24407, 24413, - 24419, 24421, 24439, 24443, 24469, 24473, 24481, 24499, 24509, 24517, - 24527, 24533, 24547, 24551, 24571, 24593, 24611, 24623, 24631, 24659, - 24671, 24677, 24683, 24691, 24697, 24709, 24733, 24749, 24763, 24767, - 24781, 24793, 24799, 24809, 24821, 24841, 24847, 24851, 24859, 24877, - 24889, 24907, 24917, 24919, 24923, 24943, 24953, 24967, 24971, 24977, - 24979, 24989, 25013, 25031, 25033, 25037, 25057, 25073, 25087, 25097, - 25111, 25117, 25121, 25127, 25147, 25153, 25163, 25169, 25171, 25183, - 25189, 25219, 25229, 25237, 25243, 25247, 25253, 25261, 25301, 25303, - 25307, 25309, 25321, 25339, 25343, 25349, 25357, 25367, 25373, 25391, - 25409, 25411, 25423, 25439, 25447, 25453, 25457, 25463, 25469, 25471, - 25523, 25537, 25541, 25561, 25577, 25579, 25583, 25589, 25601, 25603, - 25609, 25621, 25633, 25639, 25643, 25657, 25667, 25673, 25679, 25693, - 25703, 25717, 25733, 25741, 25747, 25759, 25763, 25771, 25793, 25799, - 25801, 25819, 25841, 25847, 25849, 25867, 25873, 25889, 25903, 25913, - 25919, 25931, 25933, 25939, 25943, 25951, 25969, 25981, 25997, 25999, - 26003, 26017, 26021, 26029, 26041, 26053, 26083, 26099, 26107, 26111, - 26113, 26119, 26141, 26153, 26161, 26171, 26177, 26183, 26189, 26203, - 26209, 26227, 26237, 26249, 26251, 26261, 26263, 26267, 26293, 26297, - 26309, 26317, 26321, 26339, 26347, 26357, 26371, 26387, 26393, 26399, - 26407, 26417, 26423, 26431, 26437, 26449, 26459, 26479, 26489, 26497, - 26501, 26513, 26539, 26557, 26561, 26573, 26591, 26597, 26627, 26633, - 26641, 26647, 26669, 26681, 26683, 26687, 26693, 26699, 26701, 26711, - 26713, 26717, 26723, 26729, 26731, 26737, 26759, 26777, 26783, 26801, - 26813, 26821, 26833, 26839, 26849, 26861, 26863, 26879, 26881, 26891, - 26893, 26903, 26921, 26927, 26947, 26951, 26953, 26959, 26981, 26987, - 26993, 27011, 27017, 27031, 27043, 27059, 27061, 27067, 27073, 27077, - 27091, 27103, 27107, 27109, 27127, 27143, 27179, 27191, 27197, 27211, - 27239, 27241, 27253, 27259, 27271, 27277, 27281, 27283, 27299, 27329, - 27337, 27361, 27367, 27397, 27407, 27409, 27427, 27431, 27437, 27449, - 27457, 27479, 27481, 27487, 27509, 27527, 27529, 27539, 27541, 27551, - 27581, 27583, 27611, 27617, 27631, 27647, 27653, 27673, 27689, 27691, - 27697, 27701, 27733, 27737, 27739, 27743, 27749, 27751, 27763, 27767, - 27773, 27779, 27791, 27793, 27799, 27803, 27809, 27817, 27823, 27827, - 27847, 27851, 27883, 27893, 27901, 27917, 27919, 27941, 27943, 27947, - 27953, 27961, 27967, 27983, 27997, 28001, 28019, 28027, 28031, 28051, - 28057, 28069, 28081, 28087, 28097, 28099, 28109, 28111, 28123, 28151, - 28163, 28181, 28183, 28201, 28211, 28219, 28229, 28277, 28279, 28283, - 28289, 28297, 28307, 28309, 28319, 28349, 28351, 28387, 28393, 28403, - 28409, 28411, 28429, 28433, 28439, 28447, 28463, 28477, 28493, 28499, - 28513, 28517, 28537, 28541, 28547, 28549, 28559, 28571, 28573, 28579, - 28591, 28597, 28603, 28607, 28619, 28621, 28627, 28631, 28643, 28649, - 28657, 28661, 28663, 28669, 28687, 28697, 28703, 28711, 28723, 28729, - 28751, 28753, 28759, 28771, 28789, 28793, 28807, 28813, 28817, 28837, - 28843, 28859, 28867, 28871, 28879, 28901, 28909, 28921, 28927, 28933, - 28949, 28961, 28979, 29009, 29017, 29021, 29023, 29027, 29033, 29059, - 29063, 29077, 29101, 29123, 29129, 29131, 29137, 29147, 29153, 29167, - 29173, 29179, 29191, 29201, 29207, 29209, 29221, 29231, 29243, 29251, - 29269, 29287, 29297, 29303, 29311, 29327, 29333, 29339, 29347, 29363, - 29383, 29387, 29389, 29399, 29401, 29411, 29423, 29429, 29437, 29443, - 29453, 29473, 29483, 29501, 29527, 29531, 29537, 29567, 29569, 29573, - 29581, 29587, 29599, 29611, 29629, 29633, 29641, 29663, 29669, 29671, - 29683, 29717, 29723, 29741, 29753, 29759, 29761, 29789, 29803, 29819, - 29833, 29837, 29851, 29863, 29867, 29873, 29879, 29881, 29917, 29921, - 29927, 29947, 29959, 29983, 29989, 30011, 30013, 30029, 30047, 30059, - 30071, 30089, 30091, 30097, 30103, 30109, 30113, 30119, 30133, 30137, - 30139, 30161, 30169, 30181, 30187, 30197, 30203, 30211, 30223, 30241, - 30253, 30259, 30269, 30271, 30293, 30307, 30313, 30319, 30323, 30341, - 30347, 30367, 30389, 30391, 30403, 30427, 30431, 30449, 30467, 30469, - 30491, 30493, 30497, 30509, 30517, 30529, 30539, 30553, 30557, 30559, - 30577, 30593, 30631, 30637, 30643, 30649, 30661, 30671, 30677, 30689, - 30697, 30703, 30707, 30713, 30727, 30757, 30763, 30773, 30781, 30803, - 30809, 30817, 30829, 30839, 30841, 30851, 30853, 30859, 30869, 30871, - 30881, 30893, 30911, 30931, 30937, 30941, 30949, 30971, 30977, 30983, - 31013, 31019, 31033, 31039, 31051, 31063, 31069, 31079, 31081, 31091, - 31121, 31123, 31139, 31147, 31151, 31153, 31159, 31177, 31181, 31183, - 31189, 31193, 31219, 31223, 31231, 31237, 31247, 31249, 31253, 31259, - 31267, 31271, 31277, 31307, 31319, 31321, 31327, 31333, 31337, 31357, - 31379, 31387, 31391, 31393, 31397, 31469, 31477, 31481, 31489, 31511, - 31513, 31517, 31531, 31541, 31543, 31547, 31567, 31573, 31583, 31601, - 31607, 31627, 31643, 31649, 31657, 31663, 31667, 31687, 31699, 31721, - 31723, 31727, 31729, 31741, 31751, 31769, 31771, 31793, 31799, 31817, - 31847, 31849, 31859, 31873, 31883, 31891, 31907, 31957, 31963, 31973, - 31981, 31991, 32003, 32009, 32027, 32029, 32051, 32057, 32059, 32063, - 32069, 32077, 32083, 32089, 32099, 32117, 32119, 32141, 32143, 32159, - 32173, 32183, 32189, 32191, 32203, 32213, 32233, 32237, 32251, 32257, - 32261, 32297, 32299, 32303, 32309, 32321, 32323, 32327, 32341, 32353, - 32359, 32363, 32369, 32371, 32377, 32381, 32401, 32411, 32413, 32423, - 32429, 32441, 32443, 32467, 32479, 32491, 32497, 32503, 32507, 32531, - 32533, 32537, 32561, 32563, 32569, 32573, 32579, 32587, 32603, 32609, - 32611, 32621, 32633, 32647, 32653, 32687, 32693, 32707, 32713, 32717, - 32719, 32749, 32771, 32779, 32783, 32789, 32797, 32801, 32803, 32831, - 32833, 32839, 32843, 32869, 32887, 32909, 32911, 32917, 32933, 32939, - 32941, 32957, 32969, 32971, 32983, 32987, 32993, 32999, 33013, 33023, - 33029, 33037, 33049, 33053, 33071, 33073, 33083, 33091, 33107, 33113, - 33119, 33149, 33151, 33161, 33179, 33181, 33191, 33199, 33203, 33211, - 33223, 33247, 33287, 33289, 33301, 33311, 33317, 33329, 33331, 33343, - 33347, 33349, 33353, 33359, 33377, 33391, 33403, 33409, 33413, 33427, - 33457, 33461, 33469, 33479, 33487, 33493, 33503, 33521, 33529, 33533, - 33547, 33563, 33569, 33577, 33581, 33587, 33589, 33599, 33601, 33613, - 33617, 33619, 33623, 33629, 33637, 33641, 33647, 33679, 33703, 33713, - 33721, 33739, 33749, 33751, 33757, 33767, 33769, 33773, 33791, 33797, - 33809, 33811, 33827, 33829, 33851, 33857, 33863, 33871, 33889, 33893, - 33911, 33923, 33931, 33937, 33941, 33961, 33967, 33997, 34019, 34031, - 34033, 34039, 34057, 34061, 34123, 34127, 34129, 34141, 34147, 34157, - 34159, 34171, 34183, 34211, 34213, 34217, 34231, 34253, 34259, 34261, - 34267, 34273, 34283, 34297, 34301, 34303, 34313, 34319, 34327, 34337, - 34351, 34361, 34367, 34369, 34381, 34403, 34421, 34429, 34439, 34457, - 34469, 34471, 34483, 34487, 34499, 34501, 34511, 34513, 34519, 34537, - 34543, 34549, 34583, 34589, 34591, 34603, 34607, 34613, 34631, 34649, - 34651, 34667, 34673, 34679, 34687, 34693, 34703, 34721, 34729, 34739, - 34747, 34757, 34759, 34763, 34781, 34807, 34819, 34841, 34843, 34847, - 34849, 34871, 34877, 34883, 34897, 34913, 34919, 34939, 34949, 34961, - 34963, 34981, 35023, 35027, 35051, 35053, 35059, 35069, 35081, 35083, - 35089, 35099, 35107, 35111, 35117, 35129, 35141, 35149, 35153, 35159, - 35171, 35201, 35221, 35227, 35251, 35257, 35267, 35279, 35281, 35291, - 35311, 35317, 35323, 35327, 35339, 35353, 35363, 35381, 35393, 35401, - 35407, 35419, 35423, 35437, 35447, 35449, 35461, 35491, 35507, 35509, - 35521, 35527, 35531, 35533, 35537, 35543, 35569, 35573, 35591, 35593, - 35597, 35603, 35617, 35671, 35677, 35729, 35731, 35747, 35753, 35759, - 35771, 35797, 35801, 35803, 35809, 35831, 35837, 35839, 35851, 35863, - 35869, 35879, 35897, 35899, 35911, 35923, 35933, 35951, 35963, 35969, - 35977, 35983, 35993, 35999, 36007, 36011, 36013, 36017, 36037, 36061, - 36067, 36073, 36083, 36097, 36107, 36109, 36131, 36137, 36151, 36161, - 36187, 36191, 36209, 36217, 36229, 36241, 36251, 36263, 36269, 36277, - 36293, 36299, 36307, 36313, 36319, 36341, 36343, 36353, 36373, 36383, - 36389, 36433, 36451, 36457, 36467, 36469, 36473, 36479, 36493, 36497, - 36523, 36527, 36529, 36541, 36551, 36559, 36563, 36571, 36583, 36587, - 36599, 36607, 36629, 36637, 36643, 36653, 36671, 36677, 36683, 36691, - 36697, 36709, 36713, 36721, 36739, 36749, 36761, 36767, 36779, 36781, - 36787, 36791, 36793, 36809, 36821, 36833, 36847, 36857, 36871, 36877, - 36887, 36899, 36901, 36913, 36919, 36923, 36929, 36931, 36943, 36947, - 36973, 36979, 36997, 37003, 37013, 37019, 37021, 37039, 37049, 37057, - 37061, 37087, 37097, 37117, 37123, 37139, 37159, 37171, 37181, 37189, - 37199, 37201, 37217, 37223, 37243, 37253, 37273, 37277, 37307, 37309, - 37313, 37321, 37337, 37339, 37357, 37361, 37363, 37369, 37379, 37397, - 37409, 37423, 37441, 37447, 37463, 37483, 37489, 37493, 37501, 37507, - 37511, 37517, 37529, 37537, 37547, 37549, 37561, 37567, 37571, 37573, - 37579, 37589, 37591, 37607, 37619, 37633, 37643, 37649, 37657, 37663, - 37691, 37693, 37699, 37717, 37747, 37781, 37783, 37799, 37811, 37813, - 37831, 37847, 37853, 37861, 37871, 37879, 37889, 37897, 37907, 37951, - 37957, 37963, 37967, 37987, 37991, 37993, 37997, 38011, 38039, 38047, - 38053, 38069, 38083, 38113, 38119, 38149, 38153, 38167, 38177, 38183, - 38189, 38197, 38201, 38219, 38231, 38237, 38239, 38261, 38273, 38281, - 38287, 38299, 38303, 38317, 38321, 38327, 38329, 38333, 38351, 38371, - 38377, 38393, 38431, 38447, 38449, 38453, 38459, 38461, 38501, 38543, - 38557, 38561, 38567, 38569, 38593, 38603, 38609, 38611, 38629, 38639, - 38651, 38653, 38669, 38671, 38677, 38693, 38699, 38707, 38711, 38713, - 38723, 38729, 38737, 38747, 38749, 38767, 38783, 38791, 38803, 38821, - 38833, 38839, 38851, 38861, 38867, 38873, 38891, 38903, 38917, 38921, - 38923, 38933, 38953, 38959, 38971, 38977, 38993, 39019, 39023, 39041, - 39043, 39047, 39079, 39089, 39097, 39103, 39107, 39113, 39119, 39133, - 39139, 39157, 39161, 39163, 39181, 39191, 39199, 39209, 39217, 39227, - 39229, 39233, 39239, 39241, 39251, 39293, 39301, 39313, 39317, 39323, - 39341, 39343, 39359, 39367, 39371, 39373, 39383, 39397, 39409, 39419, - 39439, 39443, 39451, 39461, 39499, 39503, 39509, 39511, 39521, 39541, - 39551, 39563, 39569, 39581, 39607, 39619, 39623, 39631, 39659, 39667, - 39671, 39679, 39703, 39709, 39719, 39727, 39733, 39749, 39761, 39769, - 39779, 39791, 39799, 39821, 39827, 39829, 39839, 39841, 39847, 39857, - 39863, 39869, 39877, 39883, 39887, 39901, 39929, 39937, 39953, 39971, - 39979, 39983, 39989, 40009, 40013, 40031, 40037, 40039, 40063, 40087, - 40093, 40099, 40111, 40123, 40127, 40129, 40151, 40153, 40163, 40169, - 40177, 40189, 40193, 40213, 40231, 40237, 40241, 40253, 40277, 40283, - 40289, 40343, 40351, 40357, 40361, 40387, 40423, 40427, 40429, 40433, - 40459, 40471, 40483, 40487, 40493, 40499, 40507, 40519, 40529, 40531, - 40543, 40559, 40577, 40583, 40591, 40597, 40609, 40627, 40637, 40639, - 40693, 40697, 40699, 40709, 40739, 40751, 40759, 40763, 40771, 40787, - 40801, 40813, 40819, 40823, 40829, 40841, 40847, 40849, 40853, 40867, - 40879, 40883, 40897, 40903, 40927, 40933, 40939, 40949, 40961, 40973, - 40993, 41011, 41017, 41023, 41039, 41047, 41051, 41057, 41077, 41081, - 41113, 41117, 41131, 41141, 41143, 41149, 41161, 41177, 41179, 41183, - 41189, 41201, 41203, 41213, 41221, 41227, 41231, 41233, 41243, 41257, - 41263, 41269, 41281, 41299, 41333, 41341, 41351, 41357, 41381, 41387, - 41389, 41399, 41411, 41413, 41443, 41453, 41467, 41479, 41491, 41507, - 41513, 41519, 41521, 41539, 41543, 41549, 41579, 41593, 41597, 41603, - 41609, 41611, 41617, 41621, 41627, 41641, 41647, 41651, 41659, 41669, - 41681, 41687, 41719, 41729, 41737, 41759, 41761, 41771, 41777, 41801, - 41809, 41813, 41843, 41849, 41851, 41863, 41879, 41887, 41893, 41897, - 41903, 41911, 41927, 41941, 41947, 41953, 41957, 41959, 41969, 41981, - 41983, 41999, 42013, 42017, 42019, 42023, 42043, 42061, 42071, 42073, - 42083, 42089, 42101, 42131, 42139, 42157, 42169, 42179, 42181, 42187, - 42193, 42197, 42209, 42221, 42223, 42227, 42239, 42257, 42281, 42283, - 42293, 42299, 42307, 42323, 42331, 42337, 42349, 42359, 42373, 42379, - 42391, 42397, 42403, 42407, 42409, 42433, 42437, 42443, 42451, 42457, - 42461, 42463, 42467, 42473, 42487, 42491, 42499, 42509, 42533, 42557, - 42569, 42571, 42577, 42589, 42611, 42641, 42643, 42649, 42667, 42677, - 42683, 42689, 42697, 42701, 42703, 42709, 42719, 42727, 42737, 42743, - 42751, 42767, 42773, 42787, 42793, 42797, 42821, 42829, 42839, 42841, - 42853, 42859, 42863, 42899, 42901, 42923, 42929, 42937, 42943, 42953, - 42961, 42967, 42979, 42989, 43003, 43013, 43019, 43037, 43049, 43051, - 43063, 43067, 43093, 43103, 43117, 43133, 43151, 43159, 43177, 43189, - 43201, 43207, 43223, 43237, 43261, 43271, 43283, 43291, 43313, 43319, - 43321, 43331, 43391, 43397, 43399, 43403, 43411, 43427, 43441, 43451, - 43457, 43481, 43487, 43499, 43517, 43541, 43543, 43573, 43577, 43579, - 43591, 43597, 43607, 43609, 43613, 43627, 43633, 43649, 43651, 43661, - 43669, 43691, 43711, 43717, 43721, 43753, 43759, 43777, 43781, 43783, - 43787, 43789, 43793, 43801, 43853, 43867, 43889, 43891, 43913, 43933, - 43943, 43951, 43961, 43963, 43969, 43973, 43987, 43991, 43997, 44017, - 44021, 44027, 44029, 44041, 44053, 44059, 44071, 44087, 44089, 44101, - 44111, 44119, 44123, 44129, 44131, 44159, 44171, 44179, 44189, 44201, - 44203, 44207, 44221, 44249, 44257, 44263, 44267, 44269, 44273, 44279, - 44281, 44293, 44351, 44357, 44371, 44381, 44383, 44389, 44417, 44449, - 44453, 44483, 44491, 44497, 44501, 44507, 44519, 44531, 44533, 44537, - 44543, 44549, 44563, 44579, 44587, 44617, 44621, 44623, 44633, 44641, - 44647, 44651, 44657, 44683, 44687, 44699, 44701, 44711, 44729, 44741, - 44753, 44771, 44773, 44777, 44789, 44797, 44809, 44819, 44839, 44843, - 44851, 44867, 44879, 44887, 44893, 44909, 44917, 44927, 44939, 44953, - 44959, 44963, 44971, 44983, 44987, 45007, 45013, 45053, 45061, 45077, - 45083, 45119, 45121, 45127, 45131, 45137, 45139, 45161, 45179, 45181, - 45191, 45197, 45233, 45247, 45259, 45263, 45281, 45289, 45293, 45307, - 45317, 45319, 45329, 45337, 45341, 45343, 45361, 45377, 45389, 45403, - 45413, 45427, 45433, 45439, 45481, 45491, 45497, 45503, 45523, 45533, - 45541, 45553, 45557, 45569, 45587, 45589, 45599, 45613, 45631, 45641, - 45659, 45667, 45673, 45677, 45691, 45697, 45707, 45737, 45751, 45757, - 45763, 45767, 45779, 45817, 45821, 45823, 45827, 45833, 45841, 45853, - 45863, 45869, 45887, 45893, 45943, 45949, 45953, 45959, 45971, 45979, - 45989, 46021, 46027, 46049, 46051, 46061, 46073, 46091, 46093, 46099, - 46103, 46133, 46141, 46147, 46153, 46171, 46181, 46183, 46187, 46199, - 46219, 46229, 46237, 46261, 46271, 46273, 46279, 46301, 46307, 46309, - 46327, 46337, 46349, 46351, 46381, 46399, 46411, 46439, 46441, 46447, - 46451, 46457, 46471, 46477, 46489, 46499, 46507, 46511, 46523, 46549, - 46559, 46567, 46573, 46589, 46591, 46601, 46619, 46633, 46639, 46643, - 46649, 46663, 46679, 46681, 46687, 46691, 46703, 46723, 46727, 46747, - 46751, 46757, 46769, 46771, 46807, 46811, 46817, 46819, 46829, 46831, - 46853, 46861, 46867, 46877, 46889, 46901, 46919, 46933, 46957, 46993, - 46997, 47017, 47041, 47051, 47057, 47059, 47087, 47093, 47111, 47119, - 47123, 47129, 47137, 47143, 47147, 47149, 47161, 47189, 47207, 47221, - 47237, 47251, 47269, 47279, 47287, 47293, 47297, 47303, 47309, 47317, - 47339, 47351, 47353, 47363, 47381, 47387, 47389, 47407, 47417, 47419, - 47431, 47441, 47459, 47491, 47497, 47501, 47507, 47513, 47521, 47527, - 47533, 47543, 47563, 47569, 47581, 47591, 47599, 47609, 47623, 47629, - 47639, 47653, 47657, 47659, 47681, 47699, 47701, 47711, 47713, 47717, - 47737, 47741, 47743, 47777, 47779, 47791, 47797, 47807, 47809, 47819, - 47837, 47843, 47857, 47869, 47881, 47903, 47911, 47917, 47933, 47939, - 47947, 47951, 47963, 47969, 47977, 47981, 48017, 48023, 48029, 48049, - 48073, 48079, 48091, 48109, 48119, 48121, 48131, 48157, 48163, 48179, - 48187, 48193, 48197, 48221, 48239, 48247, 48259, 48271, 48281, 48299, - 48311, 48313, 48337, 48341, 48353, 48371, 48383, 48397, 48407, 48409, - 48413, 48437, 48449, 48463, 48473, 48479, 48481, 48487, 48491, 48497, - 48523, 48527, 48533, 48539, 48541, 48563, 48571, 48589, 48593, 48611, - 48619, 48623, 48647, 48649, 48661, 48673, 48677, 48679, 48731, 48733, - 48751, 48757, 48761, 48767, 48779, 48781, 48787, 48799, 48809, 48817, - 48821, 48823, 48847, 48857, 48859, 48869, 48871, 48883, 48889, 48907, - 48947, 48953, 48973, 48989, 48991, 49003, 49009, 49019, 49031, 49033, - 49037, 49043, 49057, 49069, 49081, 49103, 49109, 49117, 49121, 49123, - 49139, 49157, 49169, 49171, 49177, 49193, 49199, 49201, 49207, 49211, - 49223, 49253, 49261, 49277, 49279, 49297, 49307, 49331, 49333, 49339, - 49363, 49367, 49369, 49391, 49393, 49409, 49411, 49417, 49429, 49433, - 49451, 49459, 49463, 49477, 49481, 49499, 49523, 49529, 49531, 49537, - 49547, 49549, 49559, 49597, 49603, 49613, 49627, 49633, 49639, 49663, - 49667, 49669, 49681, 49697, 49711, 49727, 49739, 49741, 49747, 49757, - 49783, 49787, 49789, 49801, 49807, 49811, 49823, 49831, 49843, 49853, - 49871, 49877, 49891, 49919, 49921, 49927, 49937, 49939, 49943, 49957, - 49991, 49993, 49999, 50021, 50023, 50033, 50047, 50051, 50053, 50069, - 50077, 50087, 50093, 50101, 50111, 50119, 50123, 50129, 50131, 50147, - 50153, 50159, 50177, 50207, 50221, 50227, 50231, 50261, 50263, 50273, - 50287, 50291, 50311, 50321, 50329, 50333, 50341, 50359, 50363, 50377, - 50383, 50387, 50411, 50417, 50423, 50441, 50459, 50461, 50497, 50503, - 50513, 50527, 50539, 50543, 50549, 50551, 50581, 50587, 50591, 50593, - 50599, 50627, 50647, 50651, 50671, 50683, 50707, 50723, 50741, 50753, - 50767, 50773, 50777, 50789, 50821, 50833, 50839, 50849, 50857, 50867, - 50873, 50891, 50893, 50909, 50923, 50929, 50951, 50957, 50969, 50971, - 50989, 50993, 51001, 51031, 51043, 51047, 51059, 51061, 51071, 51109, - 51131, 51133, 51137, 51151, 51157, 51169, 51193, 51197, 51199, 51203, - 51217, 51229, 51239, 51241, 51257, 51263, 51283, 51287, 51307, 51329, - 51341, 51343, 51347, 51349, 51361, 51383, 51407, 51413, 51419, 51421, - 51427, 51431, 51437, 51439, 51449, 51461, 51473, 51479, 51481, 51487, - 51503, 51511, 51517, 51521, 51539, 51551, 51563, 51577, 51581, 51593, - 51599, 51607, 51613, 51631, 51637, 51647, 51659, 51673, 51679, 51683, - 51691, 51713, 51719, 51721, 51749, 51767, 51769, 51787, 51797, 51803, - 51817, 51827, 51829, 51839, 51853, 51859, 51869, 51871, 51893, 51899, - 51907, 51913, 51929, 51941, 51949, 51971, 51973, 51977, 51991, 52009, - 52021, 52027, 52051, 52057, 52067, 52069, 52081, 52103, 52121, 52127, - 52147, 52153, 52163, 52177, 52181, 52183, 52189, 52201, 52223, 52237, - 52249, 52253, 52259, 52267, 52289, 52291, 52301, 52313, 52321, 52361, - 52363, 52369, 52379, 52387, 52391, 52433, 52453, 52457, 52489, 52501, - 52511, 52517, 52529, 52541, 52543, 52553, 52561, 52567, 52571, 52579, - 52583, 52609, 52627, 52631, 52639, 52667, 52673, 52691, 52697, 52709, - 52711, 52721, 52727, 52733, 52747, 52757, 52769, 52783, 52807, 52813, - 52817, 52837, 52859, 52861, 52879, 52883, 52889, 52901, 52903, 52919, - 52937, 52951, 52957, 52963, 52967, 52973, 52981, 52999, 53003, 53017, - 53047, 53051, 53069, 53077, 53087, 53089, 53093, 53101, 53113, 53117, - 53129, 53147, 53149, 53161, 53171, 53173, 53189, 53197, 53201, 53231, - 53233, 53239, 53267, 53269, 53279, 53281, 53299, 53309, 53323, 53327, - 53353, 53359, 53377, 53381, 53401, 53407, 53411, 53419, 53437, 53441, - 53453, 53479, 53503, 53507, 53527, 53549, 53551, 53569, 53591, 53593, - 53597, 53609, 53611, 53617, 53623, 53629, 53633, 53639, 53653, 53657, - 53681, 53693, 53699, 53717, 53719, 53731, 53759, 53773, 53777, 53783, - 53791, 53813, 53819, 53831, 53849, 53857, 53861, 53881, 53887, 53891, - 53897, 53899, 53917, 53923, 53927, 53939, 53951, 53959, 53987, 53993, - 54001, 54011, 54013, 54037, 54049, 54059, 54083, 54091, 54101, 54121, - 54133, 54139, 54151, 54163, 54167, 54181, 54193, 54217, 54251, 54269, - 54277, 54287, 54293, 54311, 54319, 54323, 54331, 54347, 54361, 54367, - 54371, 54377, 54401, 54403, 54409, 54413, 54419, 54421, 54437, 54443, - 54449, 54469, 54493, 54497, 54499, 54503, 54517, 54521, 54539, 54541, - 54547, 54559, 54563, 54577, 54581, 54583, 54601, 54617, 54623, 54629, - 54631, 54647, 54667, 54673, 54679, 54709, 54713, 54721, 54727, 54751, - 54767, 54773, 54779, 54787, 54799, 54829, 54833, 54851, 54869, 54877, - 54881, 54907, 54917, 54919, 54941, 54949, 54959, 54973, 54979, 54983, - 55001, 55009, 55021, 55049, 55051, 55057, 55061, 55073, 55079, 55103, - 55109, 55117, 55127, 55147, 55163, 55171, 55201, 55207, 55213, 55217, - 55219, 55229, 55243, 55249, 55259, 55291, 55313, 55331, 55333, 55337, - 55339, 55343, 55351, 55373, 55381, 55399, 55411, 55439, 55441, 55457, - 55469, 55487, 55501, 55511, 55529, 55541, 55547, 55579, 55589, 55603, - 55609, 55619, 55621, 55631, 55633, 55639, 55661, 55663, 55667, 55673, - 55681, 55691, 55697, 55711, 55717, 55721, 55733, 55763, 55787, 55793, - 55799, 55807, 55813, 55817, 55819, 55823, 55829, 55837, 55843, 55849, - 55871, 55889, 55897, 55901, 55903, 55921, 55927, 55931, 55933, 55949, - 55967, 55987, 55997, 56003, 56009, 56039, 56041, 56053, 56081, 56087, - 56093, 56099, 56101, 56113, 56123, 56131, 56149, 56167, 56171, 56179, - 56197, 56207, 56209, 56237, 56239, 56249, 56263, 56267, 56269, 56299, - 56311, 56333, 56359, 56369, 56377, 56383, 56393, 56401, 56417, 56431, - 56437, 56443, 56453, 56467, 56473, 56477, 56479, 56489, 56501, 56503, - 56509, 56519, 56527, 56531, 56533, 56543, 56569, 56591, 56597, 56599, - 56611, 56629, 56633, 56659, 56663, 56671, 56681, 56687, 56701, 56711, - 56713, 56731, 56737, 56747, 56767, 56773, 56779, 56783, 56807, 56809, - 56813, 56821, 56827, 56843, 56857, 56873, 56891, 56893, 56897, 56909, - 56911, 56921, 56923, 56929, 56941, 56951, 56957, 56963, 56983, 56989, - 56993, 56999, 57037, 57041, 57047, 57059, 57073, 57077, 57089, 57097, - 57107, 57119, 57131, 57139, 57143, 57149, 57163, 57173, 57179, 57191, - 57193, 57203, 57221, 57223, 57241, 57251, 57259, 57269, 57271, 57283, - 57287, 57301, 57329, 57331, 57347, 57349, 57367, 57373, 57383, 57389, - 57397, 57413, 57427, 57457, 57467, 57487, 57493, 57503, 57527, 57529, - 57557, 57559, 57571, 57587, 57593, 57601, 57637, 57641, 57649, 57653, - 57667, 57679, 57689, 57697, 57709, 57713, 57719, 57727, 57731, 57737, - 57751, 57773, 57781, 57787, 57791, 57793, 57803, 57809, 57829, 57839, - 57847, 57853, 57859, 57881, 57899, 57901, 57917, 57923, 57943, 57947, - 57973, 57977, 57991, 58013, 58027, 58031, 58043, 58049, 58057, 58061, - 58067, 58073, 58099, 58109, 58111, 58129, 58147, 58151, 58153, 58169, - 58171, 58189, 58193, 58199, 58207, 58211, 58217, 58229, 58231, 58237, - 58243, 58271, 58309, 58313, 58321, 58337, 58363, 58367, 58369, 58379, - 58391, 58393, 58403, 58411, 58417, 58427, 58439, 58441, 58451, 58453, - 58477, 58481, 58511, 58537, 58543, 58549, 58567, 58573, 58579, 58601, - 58603, 58613, 58631, 58657, 58661, 58679, 58687, 58693, 58699, 58711, - 58727, 58733, 58741, 58757, 58763, 58771, 58787, 58789, 58831, 58889, - 58897, 58901, 58907, 58909, 58913, 58921, 58937, 58943, 58963, 58967, - 58979, 58991, 58997, 59009, 59011, 59021, 59023, 59029, 59051, 59053, - 59063, 59069, 59077, 59083, 59093, 59107, 59113, 59119, 59123, 59141, - 59149, 59159, 59167, 59183, 59197, 59207, 59209, 59219, 59221, 59233, - 59239, 59243, 59263, 59273, 59281, 59333, 59341, 59351, 59357, 59359, - 59369, 59377, 59387, 59393, 59399, 59407, 59417, 59419, 59441, 59443, - 59447, 59453, 59467, 59471, 59473, 59497, 59509, 59513, 59539, 59557, - 59561, 59567, 59581, 59611, 59617, 59621, 59627, 59629, 59651, 59659, - 59663, 59669, 59671, 59693, 59699, 59707, 59723, 59729, 59743, 59747, - 59753, 59771, 59779, 59791, 59797, 59809, 59833, 59863, 59879, 59887, - 59921, 59929, 59951, 59957, 59971, 59981, 59999, 60013, 60017, 60029, - 60037, 60041, 60077, 60083, 60089, 60091, 60101, 60103, 60107, 60127, - 60133, 60139, 60149, 60161, 60167, 60169, 60209, 60217, 60223, 60251, - 60257, 60259, 60271, 60289, 60293, 60317, 60331, 60337, 60343, 60353, - 60373, 60383, 60397, 60413, 60427, 60443, 60449, 60457, 60493, 60497, - 60509, 60521, 60527, 60539, 60589, 60601, 60607, 60611, 60617, 60623, - 60631, 60637, 60647, 60649, 60659, 60661, 60679, 60689, 60703, 60719, - 60727, 60733, 60737, 60757, 60761, 60763, 60773, 60779, 60793, 60811, - 60821, 60859, 60869, 60887, 60889, 60899, 60901, 60913, 60917, 60919, - 60923, 60937, 60943, 60953, 60961, 61001, 61007, 61027, 61031, 61043, - 61051, 61057, 61091, 61099, 61121, 61129, 61141, 61151, 61153, 61169, - 61211, 61223, 61231, 61253, 61261, 61283, 61291, 61297, 61331, 61333, - 61339, 61343, 61357, 61363, 61379, 61381, 61403, 61409, 61417, 61441, - 61463, 61469, 61471, 61483, 61487, 61493, 61507, 61511, 61519, 61543, - 61547, 61553, 61559, 61561, 61583, 61603, 61609, 61613, 61627, 61631, - 61637, 61643, 61651, 61657, 61667, 61673, 61681, 61687, 61703, 61717, - 61723, 61729, 61751, 61757, 61781, 61813, 61819, 61837, 61843, 61861, - 61871, 61879, 61909, 61927, 61933, 61949, 61961, 61967, 61979, 61981, - 61987, 61991, 62003, 62011, 62017, 62039, 62047, 62053, 62057, 62071, - 62081, 62099, 62119, 62129, 62131, 62137, 62141, 62143, 62171, 62189, - 62191, 62201, 62207, 62213, 62219, 62233, 62273, 62297, 62299, 62303, - 62311, 62323, 62327, 62347, 62351, 62383, 62401, 62417, 62423, 62459, - 62467, 62473, 62477, 62483, 62497, 62501, 62507, 62533, 62539, 62549, - 62563, 62581, 62591, 62597, 62603, 62617, 62627, 62633, 62639, 62653, - 62659, 62683, 62687, 62701, 62723, 62731, 62743, 62753, 62761, 62773, - 62791, 62801, 62819, 62827, 62851, 62861, 62869, 62873, 62897, 62903, - 62921, 62927, 62929, 62939, 62969, 62971, 62981, 62983, 62987, 62989, - 63029, 63031, 63059, 63067, 63073, 63079, 63097, 63103, 63113, 63127, - 63131, 63149, 63179, 63197, 63199, 63211, 63241, 63247, 63277, 63281, - 63299, 63311, 63313, 63317, 63331, 63337, 63347, 63353, 63361, 63367, - 63377, 63389, 63391, 63397, 63409, 63419, 63421, 63439, 63443, 63463, - 63467, 63473, 63487, 63493, 63499, 63521, 63527, 63533, 63541, 63559, - 63577, 63587, 63589, 63599, 63601, 63607, 63611, 63617, 63629, 63647, - 63649, 63659, 63667, 63671, 63689, 63691, 63697, 63703, 63709, 63719, - 63727, 63737, 63743, 63761, 63773, 63781, 63793, 63799, 63803, 63809, - 63823, 63839, 63841, 63853, 63857, 63863, 63901, 63907, 63913, 63929, - 63949, 63977, 63997, 64007, 64013, 64019, 64033, 64037, 64063, 64067, - 64081, 64091, 64109, 64123, 64151, 64153, 64157, 64171, 64187, 64189, - 64217, 64223, 64231, 64237, 64271, 64279, 64283, 64301, 64303, 64319, - 64327, 64333, 64373, 64381, 64399, 64403, 64433, 64439, 64451, 64453, - 64483, 64489, 64499, 64513, 64553, 64567, 64577, 64579, 64591, 64601, - 64609, 64613, 64621, 64627, 64633, 64661, 64663, 64667, 64679, 64693, - 64709, 64717, 64747, 64763, 64781, 64783, 64793, 64811, 64817, 64849, - 64853, 64871, 64877, 64879, 64891, 64901, 64919, 64921, 64927, 64937, - 64951, 64969, 64997, 65003, 65011, 65027, 65029, 65033, 65053, 65063, - 65071, 65089, 65099, 65101, 65111, 65119, 65123, 65129, 65141, 65147, - 65167, 65171, 65173, 65179, 65183, 65203, 65213, 65239, 65257, 65267, - 65269, 65287, 65293, 65309, 65323, 65327, 65353, 65357, 65371, 65381, - 65393, 65407, 65413, 65419, 65423, 65437, 65447, 65449, 65479, 65497, - 65519, 65521, 65537, 65539, 65543, 65551, 65557, 65563, 65579, 65581, - 65587, 65599, 65609, 65617, 65629, 65633, 65647, 65651, 65657, 65677, - 65687, 65699, 65701, 65707, 65713, 65717, 65719, 65729, 65731, 65761, - 65777, 65789, 65809, 65827, 65831, 65837, 65839, 65843, 65851, 65867, - 65881, 65899, 65921, 65927, 65929, 65951, 65957, 65963, 65981, 65983, - 65993, 66029, 66037, 66041, 66047, 66067, 66071, 66083, 66089, 66103, - 66107, 66109, 66137, 66161, 66169, 66173, 66179, 66191, 66221, 66239, - 66271, 66293, 66301, 66337, 66343, 66347, 66359, 66361, 66373, 66377, - 66383, 66403, 66413, 66431, 66449, 66457, 66463, 66467, 66491, 66499, - 66509, 66523, 66529, 66533, 66541, 66553, 66569, 66571, 66587, 66593, - 66601, 66617, 66629, 66643, 66653, 66683, 66697, 66701, 66713, 66721, - 66733, 66739, 66749, 66751, 66763, 66791, 66797, 66809, 66821, 66841, - 66851, 66853, 66863, 66877, 66883, 66889, 66919, 66923, 66931, 66943, - 66947, 66949, 66959, 66973, 66977, 67003, 67021, 67033, 67043, 67049, - 67057, 67061, 67073, 67079, 67103, 67121, 67129, 67139, 67141, 67153, - 67157, 67169, 67181, 67187, 67189, 67211, 67213, 67217, 67219, 67231, - 67247, 67261, 67271, 67273, 67289, 67307, 67339, 67343, 67349, 67369, - 67391, 67399, 67409, 67411, 67421, 67427, 67429, 67433, 67447, 67453, - 67477, 67481, 67489, 67493, 67499, 67511, 67523, 67531, 67537, 67547, - 67559, 67567, 67577, 67579, 67589, 67601, 67607, 67619, 67631, 67651, - 67679, 67699, 67709, 67723, 67733, 67741, 67751, 67757, 67759, 67763, - 67777, 67783, 67789, 67801, 67807, 67819, 67829, 67843, 67853, 67867, - 67883, 67891, 67901, 67927, 67931, 67933, 67939, 67943, 67957, 67961, - 67967, 67979, 67987, 67993, 68023, 68041, 68053, 68059, 68071, 68087, - 68099, 68111, 68113, 68141, 68147, 68161, 68171, 68207, 68209, 68213, - 68219, 68227, 68239, 68261, 68279, 68281, 68311, 68329, 68351, 68371, - 68389, 68399, 68437, 68443, 68447, 68449, 68473, 68477, 68483, 68489, - 68491, 68501, 68507, 68521, 68531, 68539, 68543, 68567, 68581, 68597, - 68611, 68633, 68639, 68659, 68669, 68683, 68687, 68699, 68711, 68713, - 68729, 68737, 68743, 68749, 68767, 68771, 68777, 68791, 68813, 68819, - 68821, 68863, 68879, 68881, 68891, 68897, 68899, 68903, 68909, 68917, - 68927, 68947, 68963, 68993, 69001, 69011, 69019, 69029, 69031, 69061, - 69067, 69073, 69109, 69119, 69127, 69143, 69149, 69151, 69163, 69191, - 69193, 69197, 69203, 69221, 69233, 69239, 69247, 69257, 69259, 69263, - 69313, 69317, 69337, 69341, 69371, 69379, 69383, 69389, 69401, 69403, - 69427, 69431, 69439, 69457, 69463, 69467, 69473, 69481, 69491, 69493, - 69497, 69499, 69539, 69557, 69593, 69623, 69653, 69661, 69677, 69691, - 69697, 69709, 69737, 69739, 69761, 69763, 69767, 69779, 69809, 69821, - 69827, 69829, 69833, 69847, 69857, 69859, 69877, 69899, 69911, 69929, - 69931, 69941, 69959, 69991, 69997, 70001, 70003, 70009, 70019, 70039, - 70051, 70061, 70067, 70079, 70099, 70111, 70117, 70121, 70123, 70139, - 70141, 70157, 70163, 70177, 70181, 70183, 70199, 70201, 70207, 70223, - 70229, 70237, 70241, 70249, 70271, 70289, 70297, 70309, 70313, 70321, - 70327, 70351, 70373, 70379, 70381, 70393, 70423, 70429, 70439, 70451, - 70457, 70459, 70481, 70487, 70489, 70501, 70507, 70529, 70537, 70549, - 70571, 70573, 70583, 70589, 70607, 70619, 70621, 70627, 70639, 70657, - 70663, 70667, 70687, 70709, 70717, 70729, 70753, 70769, 70783, 70793, - 70823, 70841, 70843, 70849, 70853, 70867, 70877, 70879, 70891, 70901, - 70913, 70919, 70921, 70937, 70949, 70951, 70957, 70969, 70979, 70981, - 70991, 70997, 70999, 71011, 71023, 71039, 71059, 71069, 71081, 71089, - 71119, 71129, 71143, 71147, 71153, 71161, 71167, 71171, 71191, 71209, - 71233, 71237, 71249, 71257, 71261, 71263, 71287, 71293, 71317, 71327, - 71329, 71333, 71339, 71341, 71347, 71353, 71359, 71363, 71387, 71389, - 71399, 71411, 71413, 71419, 71429, 71437, 71443, 71453, 71471, 71473, - 71479, 71483, 71503, 71527, 71537, 71549, 71551, 71563, 71569, 71593, - 71597, 71633, 71647, 71663, 71671, 71693, 71699, 71707, 71711, 71713, - 71719, 71741, 71761, 71777, 71789, 71807, 71809, 71821, 71837, 71843, - 71849, 71861, 71867, 71879, 71881, 71887, 71899, 71909, 71917, 71933, - 71941, 71947, 71963, 71971, 71983, 71987, 71993, 71999, 72019, 72031, - 72043, 72047, 72053, 72073, 72077, 72089, 72091, 72101, 72103, 72109, - 72139, 72161, 72167, 72169, 72173, 72211, 72221, 72223, 72227, 72229, - 72251, 72253, 72269, 72271, 72277, 72287, 72307, 72313, 72337, 72341, - 72353, 72367, 72379, 72383, 72421, 72431, 72461, 72467, 72469, 72481, - 72493, 72497, 72503, 72533, 72547, 72551, 72559, 72577, 72613, 72617, - 72623, 72643, 72647, 72649, 72661, 72671, 72673, 72679, 72689, 72701, - 72707, 72719, 72727, 72733, 72739, 72763, 72767, 72797, 72817, 72823, - 72859, 72869, 72871, 72883, 72889, 72893, 72901, 72907, 72911, 72923, - 72931, 72937, 72949, 72953, 72959, 72973, 72977, 72997, 73009, 73013, - 73019, 73037, 73039, 73043, 73061, 73063, 73079, 73091, 73121, 73127, - 73133, 73141, 73181, 73189, 73237, 73243, 73259, 73277, 73291, 73303, - 73309, 73327, 73331, 73351, 73361, 73363, 73369, 73379, 73387, 73417, - 73421, 73433, 73453, 73459, 73471, 73477, 73483, 73517, 73523, 73529, - 73547, 73553, 73561, 73571, 73583, 73589, 73597, 73607, 73609, 73613, - 73637, 73643, 73651, 73673, 73679, 73681, 73693, 73699, 73709, 73721, - 73727, 73751, 73757, 73771, 73783, 73819, 73823, 73847, 73849, 73859, - 73867, 73877, 73883, 73897, 73907, 73939, 73943, 73951, 73961, 73973, - 73999, 74017, 74021, 74027, 74047, 74051, 74071, 74077, 74093, 74099, - 74101, 74131, 74143, 74149, 74159, 74161, 74167, 74177, 74189, 74197, - 74201, 74203, 74209, 74219, 74231, 74257, 74279, 74287, 74293, 74297, - 74311, 74317, 74323, 74353, 74357, 74363, 74377, 74381, 74383, 74411, - 74413, 74419, 74441, 74449, 74453, 74471, 74489, 74507, 74509, 74521, - 74527, 74531, 74551, 74561, 74567, 74573, 74587, 74597, 74609, 74611, - 74623, 74653, 74687, 74699, 74707, 74713, 74717, 74719, 74729, 74731, - 74747, 74759, 74761, 74771, 74779, 74797, 74821, 74827, 74831, 74843, - 74857, 74861, 74869, 74873, 74887, 74891, 74897, 74903, 74923, 74929, - 74933, 74941, 74959, 75011, 75013, 75017, 75029, 75037, 75041, 75079, - 75083, 75109, 75133, 75149, 75161, 75167, 75169, 75181, 75193, 75209, - 75211, 75217, 75223, 75227, 75239, 75253, 75269, 75277, 75289, 75307, - 75323, 75329, 75337, 75347, 75353, 75367, 75377, 75389, 75391, 75401, - 75403, 75407, 75431, 75437, 75479, 75503, 75511, 75521, 75527, 75533, - 75539, 75541, 75553, 75557, 75571, 75577, 75583, 75611, 75617, 75619, - 75629, 75641, 75653, 75659, 75679, 75683, 75689, 75703, 75707, 75709, - 75721, 75731, 75743, 75767, 75773, 75781, 75787, 75793, 75797, 75821, - 75833, 75853, 75869, 75883, 75913, 75931, 75937, 75941, 75967, 75979, - 75983, 75989, 75991, 75997, 76001, 76003, 76031, 76039, 76079, 76081, - 76091, 76099, 76103, 76123, 76129, 76147, 76157, 76159, 76163, 76207, - 76213, 76231, 76243, 76249, 76253, 76259, 76261, 76283, 76289, 76303, - 76333, 76343, 76367, 76369, 76379, 76387, 76403, 76421, 76423, 76441, - 76463, 76471, 76481, 76487, 76493, 76507, 76511, 76519, 76537, 76541, - 76543, 76561, 76579, 76597, 76603, 76607, 76631, 76649, 76651, 76667, - 76673, 76679, 76697, 76717, 76733, 76753, 76757, 76771, 76777, 76781, - 76801, 76819, 76829, 76831, 76837, 76847, 76871, 76873, 76883, 76907, - 76913, 76919, 76943, 76949, 76961, 76963, 76991, 77003, 77017, 77023, - 77029, 77041, 77047, 77069, 77081, 77093, 77101, 77137, 77141, 77153, - 77167, 77171, 77191, 77201, 77213, 77237, 77239, 77243, 77249, 77261, - 77263, 77267, 77269, 77279, 77291, 77317, 77323, 77339, 77347, 77351, - 77359, 77369, 77377, 77383, 77417, 77419, 77431, 77447, 77471, 77477, - 77479, 77489, 77491, 77509, 77513, 77521, 77527, 77543, 77549, 77551, - 77557, 77563, 77569, 77573, 77587, 77591, 77611, 77617, 77621, 77641, - 77647, 77659, 77681, 77687, 77689, 77699, 77711, 77713, 77719, 77723, - 77731, 77743, 77747, 77761, 77773, 77783, 77797, 77801, 77813, 77839, - 77849, 77863, 77867, 77893, 77899, 77929, 77933, 77951, 77969, 77977, - 77983, 77999, 78007, 78017, 78031, 78041, 78049, 78059, 78079, 78101, - 78121, 78137, 78139, 78157, 78163, 78167, 78173, 78179, 78191, 78193, - 78203, 78229, 78233, 78241, 78259, 78277, 78283, 78301, 78307, 78311, - 78317, 78341, 78347, 78367, 78401, 78427, 78437, 78439, 78467, 78479, - 78487, 78497, 78509, 78511, 78517, 78539, 78541, 78553, 78569, 78571, - 78577, 78583, 78593, 78607, 78623, 78643, 78649, 78653, 78691, 78697, - 78707, 78713, 78721, 78737, 78779, 78781, 78787, 78791, 78797, 78803, - 78809, 78823, 78839, 78853, 78857, 78877, 78887, 78889, 78893, 78901, - 78919, 78929, 78941, 78977, 78979, 78989, 79031, 79039, 79043, 79063, - 79087, 79103, 79111, 79133, 79139, 79147, 79151, 79153, 79159, 79181, - 79187, 79193, 79201, 79229, 79231, 79241, 79259, 79273, 79279, 79283, - 79301, 79309, 79319, 79333, 79337, 79349, 79357, 79367, 79379, 79393, - 79397, 79399, 79411, 79423, 79427, 79433, 79451, 79481, 79493, 79531, - 79537, 79549, 79559, 79561, 79579, 79589, 79601, 79609, 79613, 79621, - 79627, 79631, 79633, 79657, 79669, 79687, 79691, 79693, 79697, 79699, - 79757, 79769, 79777, 79801, 79811, 79813, 79817, 79823, 79829, 79841, - 79843, 79847, 79861, 79867, 79873, 79889, 79901, 79903, 79907, 79939, - 79943, 79967, 79973, 79979, 79987, 79997, 79999, 80021, 80039, 80051, - 80071, 80077, 80107, 80111, 80141, 80147, 80149, 80153, 80167, 80173, - 80177, 80191, 80207, 80209, 80221, 80231, 80233, 80239, 80251, 80263, - 80273, 80279, 80287, 80309, 80317, 80329, 80341, 80347, 80363, 80369, - 80387, 80407, 80429, 80447, 80449, 80471, 80473, 80489, 80491, 80513, - 80527, 80537, 80557, 80567, 80599, 80603, 80611, 80621, 80627, 80629, - 80651, 80657, 80669, 80671, 80677, 80681, 80683, 80687, 80701, 80713, - 80737, 80747, 80749, 80761, 80777, 80779, 80783, 80789, 80803, 80809, - 80819, 80831, 80833, 80849, 80863, 80897, 80909, 80911, 80917, 80923, - 80929, 80933, 80953, 80963, 80989, 81001, 81013, 81017, 81019, 81023, - 81031, 81041, 81043, 81047, 81049, 81071, 81077, 81083, 81097, 81101, - 81119, 81131, 81157, 81163, 81173, 81181, 81197, 81199, 81203, 81223, - 81233, 81239, 81281, 81283, 81293, 81299, 81307, 81331, 81343, 81349, - 81353, 81359, 81371, 81373, 81401, 81409, 81421, 81439, 81457, 81463, - 81509, 81517, 81527, 81533, 81547, 81551, 81553, 81559, 81563, 81569, - 81611, 81619, 81629, 81637, 81647, 81649, 81667, 81671, 81677, 81689, - 81701, 81703, 81707, 81727, 81737, 81749, 81761, 81769, 81773, 81799, - 81817, 81839, 81847, 81853, 81869, 81883, 81899, 81901, 81919, 81929, - 81931, 81937, 81943, 81953, 81967, 81971, 81973, 82003, 82007, 82009, - 82013, 82021, 82031, 82037, 82039, 82051, 82067, 82073, 82129, 82139, - 82141, 82153, 82163, 82171, 82183, 82189, 82193, 82207, 82217, 82219, - 82223, 82231, 82237, 82241, 82261, 82267, 82279, 82301, 82307, 82339, - 82349, 82351, 82361, 82373, 82387, 82393, 82421, 82457, 82463, 82469, - 82471, 82483, 82487, 82493, 82499, 82507, 82529, 82531, 82549, 82559, - 82561, 82567, 82571, 82591, 82601, 82609, 82613, 82619, 82633, 82651, - 82657, 82699, 82721, 82723, 82727, 82729, 82757, 82759, 82763, 82781, - 82787, 82793, 82799, 82811, 82813, 82837, 82847, 82883, 82889, 82891, - 82903, 82913, 82939, 82963, 82981, 82997, 83003, 83009, 83023, 83047, - 83059, 83063, 83071, 83077, 83089, 83093, 83101, 83117, 83137, 83177, - 83203, 83207, 83219, 83221, 83227, 83231, 83233, 83243, 83257, 83267, - 83269, 83273, 83299, 83311, 83339, 83341, 83357, 83383, 83389, 83399, - 83401, 83407, 83417, 83423, 83431, 83437, 83443, 83449, 83459, 83471, - 83477, 83497, 83537, 83557, 83561, 83563, 83579, 83591, 83597, 83609, - 83617, 83621, 83639, 83641, 83653, 83663, 83689, 83701, 83717, 83719, - 83737, 83761, 83773, 83777, 83791, 83813, 83833, 83843, 83857, 83869, - 83873, 83891, 83903, 83911, 83921, 83933, 83939, 83969, 83983, 83987, - 84011, 84017, 84047, 84053, 84059, 84061, 84067, 84089, 84121, 84127, - 84131, 84137, 84143, 84163, 84179, 84181, 84191, 84199, 84211, 84221, - 84223, 84229, 84239, 84247, 84263, 84299, 84307, 84313, 84317, 84319, - 84347, 84349, 84377, 84389, 84391, 84401, 84407, 84421, 84431, 84437, - 84443, 84449, 84457, 84463, 84467, 84481, 84499, 84503, 84509, 84521, - 84523, 84533, 84551, 84559, 84589, 84629, 84631, 84649, 84653, 84659, - 84673, 84691, 84697, 84701, 84713, 84719, 84731, 84737, 84751, 84761, - 84787, 84793, 84809, 84811, 84827, 84857, 84859, 84869, 84871, 84913, - 84919, 84947, 84961, 84967, 84977, 84979, 84991, 85009, 85021, 85027, - 85037, 85049, 85061, 85081, 85087, 85091, 85093, 85103, 85109, 85121, - 85133, 85147, 85159, 85193, 85199, 85201, 85213, 85223, 85229, 85237, - 85243, 85247, 85259, 85297, 85303, 85313, 85331, 85333, 85361, 85363, - 85369, 85381, 85411, 85427, 85429, 85439, 85447, 85451, 85453, 85469, - 85487, 85513, 85517, 85523, 85531, 85549, 85571, 85577, 85597, 85601, - 85607, 85619, 85621, 85627, 85639, 85643, 85661, 85667, 85669, 85691, - 85703, 85711, 85717, 85733, 85751, 85781, 85793, 85817, 85819, 85829, - 85831, 85837, 85843, 85847, 85853, 85889, 85903, 85909, 85931, 85933, - 85991, 85999, 86011, 86017, 86027, 86029, 86069, 86077, 86083, 86111, - 86113, 86117, 86131, 86137, 86143, 86161, 86171, 86179, 86183, 86197, - 86201, 86209, 86239, 86243, 86249, 86257, 86263, 86269, 86287, 86291, - 86293, 86297, 86311, 86323, 86341, 86351, 86353, 86357, 86369, 86371, - 86381, 86389, 86399, 86413, 86423, 86441, 86453, 86461, 86467, 86477, - 86491, 86501, 86509, 86531, 86533, 86539, 86561, 86573, 86579, 86587, - 86599, 86627, 86629, 86677, 86689, 86693, 86711, 86719, 86729, 86743, - 86753, 86767, 86771, 86783, 86813, 86837, 86843, 86851, 86857, 86861, - 86869, 86923, 86927, 86929, 86939, 86951, 86959, 86969, 86981, 86993, - 87011, 87013, 87037, 87041, 87049, 87071, 87083, 87103, 87107, 87119, - 87121, 87133, 87149, 87151, 87179, 87181, 87187, 87211, 87221, 87223, - 87251, 87253, 87257, 87277, 87281, 87293, 87299, 87313, 87317, 87323, - 87337, 87359, 87383, 87403, 87407, 87421, 87427, 87433, 87443, 87473, - 87481, 87491, 87509, 87511, 87517, 87523, 87539, 87541, 87547, 87553, - 87557, 87559, 87583, 87587, 87589, 87613, 87623, 87629, 87631, 87641, - 87643, 87649, 87671, 87679, 87683, 87691, 87697, 87701, 87719, 87721, - 87739, 87743, 87751, 87767, 87793, 87797, 87803, 87811, 87833, 87853, - 87869, 87877, 87881, 87887, 87911, 87917, 87931, 87943, 87959, 87961, - 87973, 87977, 87991, 88001, 88003, 88007, 88019, 88037, 88069, 88079, - 88093, 88117, 88129, 88169, 88177, 88211, 88223, 88237, 88241, 88259, - 88261, 88289, 88301, 88321, 88327, 88337, 88339, 88379, 88397, 88411, - 88423, 88427, 88463, 88469, 88471, 88493, 88499, 88513, 88523, 88547, - 88589, 88591, 88607, 88609, 88643, 88651, 88657, 88661, 88663, 88667, - 88681, 88721, 88729, 88741, 88747, 88771, 88789, 88793, 88799, 88801, - 88807, 88811, 88813, 88817, 88819, 88843, 88853, 88861, 88867, 88873, - 88883, 88897, 88903, 88919, 88937, 88951, 88969, 88993, 88997, 89003, - 89009, 89017, 89021, 89041, 89051, 89057, 89069, 89071, 89083, 89087, - 89101, 89107, 89113, 89119, 89123, 89137, 89153, 89189, 89203, 89209, - 89213, 89227, 89231, 89237, 89261, 89269, 89273, 89293, 89303, 89317, - 89329, 89363, 89371, 89381, 89387, 89393, 89399, 89413, 89417, 89431, - 89443, 89449, 89459, 89477, 89491, 89501, 89513, 89519, 89521, 89527, - 89533, 89561, 89563, 89567, 89591, 89597, 89599, 89603, 89611, 89627, - 89633, 89653, 89657, 89659, 89669, 89671, 89681, 89689, 89753, 89759, - 89767, 89779, 89783, 89797, 89809, 89819, 89821, 89833, 89839, 89849, - 89867, 89891, 89897, 89899, 89909, 89917, 89923, 89939, 89959, 89963, - 89977, 89983, 89989, 90001, 90007, 90011, 90017, 90019, 90023, 90031, - 90053, 90059, 90067, 90071, 90073, 90089, 90107, 90121, 90127, 90149, - 90163, 90173, 90187, 90191, 90197, 90199, 90203, 90217, 90227, 90239, - 90247, 90263, 90271, 90281, 90289, 90313, 90353, 90359, 90371, 90373, - 90379, 90397, 90401, 90403, 90407, 90437, 90439, 90469, 90473, 90481, - 90499, 90511, 90523, 90527, 90529, 90533, 90547, 90583, 90599, 90617, - 90619, 90631, 90641, 90647, 90659, 90677, 90679, 90697, 90703, 90709, - 90731, 90749, 90787, 90793, 90803, 90821, 90823, 90833, 90841, 90847, - 90863, 90887, 90901, 90907, 90911, 90917, 90931, 90947, 90971, 90977, - 90989, 90997, 91009, 91019, 91033, 91079, 91081, 91097, 91099, 91121, - 91127, 91129, 91139, 91141, 91151, 91153, 91159, 91163, 91183, 91193, - 91199, 91229, 91237, 91243, 91249, 91253, 91283, 91291, 91297, 91303, - 91309, 91331, 91367, 91369, 91373, 91381, 91387, 91393, 91397, 91411, - 91423, 91433, 91453, 91457, 91459, 91463, 91493, 91499, 91513, 91529, - 91541, 91571, 91573, 91577, 91583, 91591, 91621, 91631, 91639, 91673, - 91691, 91703, 91711, 91733, 91753, 91757, 91771, 91781, 91801, 91807, - 91811, 91813, 91823, 91837, 91841, 91867, 91873, 91909, 91921, 91939, - 91943, 91951, 91957, 91961, 91967, 91969, 91997, 92003, 92009, 92033, - 92041, 92051, 92077, 92083, 92107, 92111, 92119, 92143, 92153, 92173, - 92177, 92179, 92189, 92203, 92219, 92221, 92227, 92233, 92237, 92243, - 92251, 92269, 92297, 92311, 92317, 92333, 92347, 92353, 92357, 92363, - 92369, 92377, 92381, 92383, 92387, 92399, 92401, 92413, 92419, 92431, - 92459, 92461, 92467, 92479, 92489, 92503, 92507, 92551, 92557, 92567, - 92569, 92581, 92593, 92623, 92627, 92639, 92641, 92647, 92657, 92669, - 92671, 92681, 92683, 92693, 92699, 92707, 92717, 92723, 92737, 92753, - 92761, 92767, 92779, 92789, 92791, 92801, 92809, 92821, 92831, 92849, - 92857, 92861, 92863, 92867, 92893, 92899, 92921, 92927, 92941, 92951, - 92957, 92959, 92987, 92993, 93001, 93047, 93053, 93059, 93077, 93083, - 93089, 93097, 93103, 93113, 93131, 93133, 93139, 93151, 93169, 93179, - 93187, 93199, 93229, 93239, 93241, 93251, 93253, 93257, 93263, 93281, - 93283, 93287, 93307, 93319, 93323, 93329, 93337, 93371, 93377, 93383, - 93407, 93419, 93427, 93463, 93479, 93481, 93487, 93491, 93493, 93497, - 93503, 93523, 93529, 93553, 93557, 93559, 93563, 93581, 93601, 93607, - 93629, 93637, 93683, 93701, 93703, 93719, 93739, 93761, 93763, 93787, - 93809, 93811, 93827, 93851, 93871, 93887, 93889, 93893, 93901, 93911, - 93913, 93923, 93937, 93941, 93949, 93967, 93971, 93979, 93983, 93997, - 94007, 94009, 94033, 94049, 94057, 94063, 94079, 94099, 94109, 94111, - 94117, 94121, 94151, 94153, 94169, 94201, 94207, 94219, 94229, 94253, - 94261, 94273, 94291, 94307, 94309, 94321, 94327, 94331, 94343, 94349, - 94351, 94379, 94397, 94399, 94421, 94427, 94433, 94439, 94441, 94447, - 94463, 94477, 94483, 94513, 94529, 94531, 94541, 94543, 94547, 94559, - 94561, 94573, 94583, 94597, 94603, 94613, 94621, 94649, 94651, 94687, - 94693, 94709, 94723, 94727, 94747, 94771, 94777, 94781, 94789, 94793, - 94811, 94819, 94823, 94837, 94841, 94847, 94849, 94873, 94889, 94903, - 94907, 94933, 94949, 94951, 94961, 94993, 94999, 95003, 95009, 95021, - 95027, 95063, 95071, 95083, 95087, 95089, 95093, 95101, 95107, 95111, - 95131, 95143, 95153, 95177, 95189, 95191, 95203, 95213, 95219, 95231, - 95233, 95239, 95257, 95261, 95267, 95273, 95279, 95287, 95311, 95317, - 95327, 95339, 95369, 95383, 95393, 95401, 95413, 95419, 95429, 95441, - 95443, 95461, 95467, 95471, 95479, 95483, 95507, 95527, 95531, 95539, - 95549, 95561, 95569, 95581, 95597, 95603, 95617, 95621, 95629, 95633, - 95651, 95701, 95707, 95713, 95717, 95723, 95731, 95737, 95747, 95773, - 95783, 95789, 95791, 95801, 95803, 95813, 95819, 95857, 95869, 95873, - 95881, 95891, 95911, 95917, 95923, 95929, 95947, 95957, 95959, 95971, - 95987, 95989, 96001, 96013, 96017, 96043, 96053, 96059, 96079, 96097, - 96137, 96149, 96157, 96167, 96179, 96181, 96199, 96211, 96221, 96223, - 96233, 96259, 96263, 96269, 96281, 96289, 96293, 96323, 96329, 96331, - 96337, 96353, 96377, 96401, 96419, 96431, 96443, 96451, 96457, 96461, - 96469, 96479, 96487, 96493, 96497, 96517, 96527, 96553, 96557, 96581, - 96587, 96589, 96601, 96643, 96661, 96667, 96671, 96697, 96703, 96731, - 96737, 96739, 96749, 96757, 96763, 96769, 96779, 96787, 96797, 96799, - 96821, 96823, 96827, 96847, 96851, 96857, 96893, 96907, 96911, 96931, - 96953, 96959, 96973, 96979, 96989, 96997, 97001, 97003, 97007, 97021, - 97039, 97073, 97081, 97103, 97117, 97127, 97151, 97157, 97159, 97169, - 97171, 97177, 97187, 97213, 97231, 97241, 97259, 97283, 97301, 97303, - 97327, 97367, 97369, 97373, 97379, 97381, 97387, 97397, 97423, 97429, - 97441, 97453, 97459, 97463, 97499, 97501, 97511, 97523, 97547, 97549, - 97553, 97561, 97571, 97577, 97579, 97583, 97607, 97609, 97613, 97649, - 97651, 97673, 97687, 97711, 97729, 97771, 97777, 97787, 97789, 97813, - 97829, 97841, 97843, 97847, 97849, 97859, 97861, 97871, 97879, 97883, - 97919, 97927, 97931, 97943, 97961, 97967, 97973, 97987, 98009, 98011, - 98017, 98041, 98047, 98057, 98081, 98101, 98123, 98129, 98143, 98179, - 98207, 98213, 98221, 98227, 98251, 98257, 98269, 98297, 98299, 98317, - 98321, 98323, 98327, 98347, 98369, 98377, 98387, 98389, 98407, 98411, - 98419, 98429, 98443, 98453, 98459, 98467, 98473, 98479, 98491, 98507, - 98519, 98533, 98543, 98561, 98563, 98573, 98597, 98621, 98627, 98639, - 98641, 98663, 98669, 98689, 98711, 98713, 98717, 98729, 98731, 98737, - 98773, 98779, 98801, 98807, 98809, 98837, 98849, 98867, 98869, 98873, - 98887, 98893, 98897, 98899, 98909, 98911, 98927, 98929, 98939, 98947, - 98953, 98963, 98981, 98993, 98999, 99013, 99017, 99023, 99041, 99053, - 99079, 99083, 99089, 99103, 99109, 99119, 99131, 99133, 99137, 99139, - 99149, 99173, 99181, 99191, 99223, 99233, 99241, 99251, 99257, 99259, - 99277, 99289, 99317, 99347, 99349, 99367, 99371, 99377, 99391, 99397, - 99401, 99409, 99431, 99439, 99469, 99487, 99497, 99523, 99527, 99529, - 99551, 99559, 99563, 99571, 99577, 99581, 99607, 99611, 99623, 99643, - 99661, 99667, 99679, 99689, 99707, 99709, 99713, 99719, 99721, 99733, - 99761, 99767, 99787, 99793, 99809, 99817, 99823, 99829, 99833, 99839, - 99859, 99871, 99877, 99881, 99901, 99907, 99923, 99929, 99961, 99971, - 99989, 99991, 100003, 100019, 100043, 100049, 100057, 100069, 100103, 100109, -100129, 100151, 100153, 100169, 100183, 100189, 100193, 100207, 100213, 100237, -100267, 100271, 100279, 100291, 100297, 100313, 100333, 100343, 100357, 100361, -100363, 100379, 100391, 100393, 100403, 100411, 100417, 100447, 100459, 100469, -100483, 100493, 100501, 100511, 100517, 100519, 100523, 100537, 100547, 100549, -100559, 100591, 100609, 100613, 100621, 100649, 100669, 100673, 100693, 100699, -100703, 100733, 100741, 100747, 100769, 100787, 100799, 100801, 100811, 100823, -100829, 100847, 100853, 100907, 100913, 100927, 100931, 100937, 100943, 100957, -100981, 100987, 100999, 101009, 101021, 101027, 101051, 101063, 101081, 101089, -101107, 101111, 101113, 101117, 101119, 101141, 101149, 101159, 101161, 101173, -101183, 101197, 101203, 101207, 101209, 101221, 101267, 101273, 101279, 101281, -101287, 101293, 101323, 101333, 101341, 101347, 101359, 101363, 101377, 101383, -101399, 101411, 101419, 101429, 101449, 101467, 101477, 101483, 101489, 101501, -101503, 101513, 101527, 101531, 101533, 101537, 101561, 101573, 101581, 101599, -101603, 101611, 101627, 101641, 101653, 101663, 101681, 101693, 101701, 101719, -101723, 101737, 101741, 101747, 101749, 101771, 101789, 101797, 101807, 101833, -101837, 101839, 101863, 101869, 101873, 101879, 101891, 101917, 101921, 101929, -101939, 101957, 101963, 101977, 101987, 101999, 102001, 102013, 102019, 102023, -102031, 102043, 102059, 102061, 102071, 102077, 102079, 102101, 102103, 102107, -102121, 102139, 102149, 102161, 102181, 102191, 102197, 102199, 102203, 102217, -102229, 102233, 102241, 102251, 102253, 102259, 102293, 102299, 102301, 102317, -102329, 102337, 102359, 102367, 102397, 102407, 102409, 102433, 102437, 102451, -102461, 102481, 102497, 102499, 102503, 102523, 102533, 102539, 102547, 102551, -102559, 102563, 102587, 102593, 102607, 102611, 102643, 102647, 102653, 102667, -102673, 102677, 102679, 102701, 102761, 102763, 102769, 102793, 102797, 102811, -102829, 102841, 102859, 102871, 102877, 102881, 102911, 102913, 102929, 102931, -102953, 102967, 102983, 103001, 103007, 103043, 103049, 103067, 103069, 103079, -103087, 103091, 103093, 103099, 103123, 103141, 103171, 103177, 103183, 103217, -103231, 103237, 103289, 103291, 103307, 103319, 103333, 103349, 103357, 103387, -103391, 103393, 103399, 103409, 103421, 103423, 103451, 103457, 103471, 103483, -103511, 103529, 103549, 103553, 103561, 103567, 103573, 103577, 103583, 103591, -103613, 103619, 103643, 103651, 103657, 103669, 103681, 103687, 103699, 103703, -103723, 103769, 103787, 103801, 103811, 103813, 103837, 103841, 103843, 103867, -103889, 103903, 103913, 103919, 103951, 103963, 103967, 103969, 103979, 103981, -103991, 103993, 103997, 104003, 104009, 104021, 104033, 104047, 104053, 104059, -104087, 104089, 104107, 104113, 104119, 104123, 104147, 104149, 104161, 104173, -104179, 104183, 104207, 104231, 104233, 104239, 104243, 104281, 104287, 104297, -104309, 104311, 104323, 104327, 104347, 104369, 104381, 104383, 104393, 104399, -104417, 104459, 104471, 104473, 104479, 104491, 104513, 104527, 104537, 104543, -104549, 104551, 104561, 104579, 104593, 104597, 104623, 104639, 104651, 104659, -104677, 104681, 104683, 104693, 104701, 104707, 104711, 104717, 104723, 104729, -) diff --git a/Crypto/Util/number.pyi b/Crypto/Util/number.pyi deleted file mode 100644 index f8680bf..0000000 --- a/Crypto/Util/number.pyi +++ /dev/null @@ -1,19 +0,0 @@ -from typing import List, Optional, Callable - - -def ceil_div(n: int, d: int) -> int: ... -def size (N: int) -> int: ... -def getRandomInteger(N: int, randfunc: Optional[Callable]=None) -> int: ... -def getRandomRange(a: int, b: int, randfunc: Optional[Callable]=None) -> int: ... -def getRandomNBitInteger(N: int, randfunc: Optional[Callable]=None) -> int: ... -def GCD(x: int,y: int) -> int: ... -def inverse(u: int, v: int) -> int: ... -def getPrime(N: int, randfunc: Optional[Callable]=None) -> int: ... -def getStrongPrime(N: int, e: Optional[int]=0, false_positive_prob: Optional[float]=1e-6, randfunc: Optional[Callable]=None) -> int: ... -def isPrime(N: int, false_positive_prob: Optional[float]=1e-6, randfunc: Optional[Callable]=None) -> bool: ... -def long_to_bytes(n: int, blocksize: Optional[int]=0) -> bytes: ... -def bytes_to_long(s: bytes) -> int: ... -def long2str(n: int, blocksize: Optional[int]=0) -> bytes: ... -def str2long(s: bytes) -> int: ... - -sieve_base: List[int] diff --git a/Crypto/Util/py3compat.py b/Crypto/Util/py3compat.py deleted file mode 100644 index cf9bb92..0000000 --- a/Crypto/Util/py3compat.py +++ /dev/null @@ -1,160 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Util/py3compat.py : Compatibility code for handling Py3k / Python 2.x -# -# Written in 2010 by Thorsten Behrens -# -# =================================================================== -# 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. -# =================================================================== - -"""Compatibility code for handling string/bytes changes from Python 2.x to Py3k - -In Python 2.x, strings (of type ''str'') contain binary data, including encoded -Unicode text (e.g. UTF-8). The separate type ''unicode'' holds Unicode text. -Unicode literals are specified via the u'...' prefix. Indexing or slicing -either type always produces a string of the same type as the original. -Data read from a file is always of '''str'' type. - -In Python 3.x, strings (type ''str'') may only contain Unicode text. The u'...' -prefix and the ''unicode'' type are now redundant. A new type (called -''bytes'') has to be used for binary data (including any particular -''encoding'' of a string). The b'...' prefix allows one to specify a binary -literal. Indexing or slicing a string produces another string. Slicing a byte -string produces another byte string, but the indexing operation produces an -integer. Data read from a file is of '''str'' type if the file was opened in -text mode, or of ''bytes'' type otherwise. - -Since PyCrypto aims at supporting both Python 2.x and 3.x, the following helper -functions are used to keep the rest of the library as independent as possible -from the actual Python version. - -In general, the code should always deal with binary strings, and use integers -instead of 1-byte character strings. - -b(s) - Take a text string literal (with no prefix or with u'...' prefix) and - make a byte string. -bchr(c) - Take an integer and make a 1-character byte string. -bord(c) - Take the result of indexing on a byte string and make an integer. -tobytes(s) - Take a text string, a byte string, or a sequence of character taken from - a byte string and make a byte string. -""" - -import sys -import abc - - -if sys.version_info[0] == 2: - def b(s): - return s - def bchr(s): - return chr(s) - def bstr(s): - return str(s) - def bord(s): - return ord(s) - def tobytes(s, encoding="latin-1"): - if isinstance(s, unicode): - return s.encode(encoding) - elif isinstance(s, str): - return s - elif isinstance(s, bytearray): - return bytes(s) - else: - return ''.join(s) - def tostr(bs): - return bs - def byte_string(s): - return isinstance(s, str) - - # In Pyton 2.x, StringIO is a stand-alone module - from StringIO import StringIO as BytesIO - - from sys import maxint - - iter_range = xrange - - def is_native_int(x): - return isinstance(x, (int, long)) - - def is_string(x): - return isinstance(x, basestring) - - ABC = abc.ABCMeta('ABC', (object,), {'__slots__': ()}) - - FileNotFoundError = IOError - -else: - def b(s): - return s.encode("latin-1") # utf-8 would cause some side-effects we don't want - def bchr(s): - return bytes([s]) - def bstr(s): - if isinstance(s,str): - return bytes(s,"latin-1") - else: - return bytes(s) - def bord(s): - return s - def tobytes(s, encoding="latin-1"): - if isinstance(s, bytes): - return s - elif isinstance(s, bytearray): - return bytes(s) - elif isinstance(s,str): - return s.encode(encoding) - else: - return bytes([s]) - def tostr(bs): - return bs.decode("latin-1") - def byte_string(s): - return isinstance(s, bytes) - - # In Python 3.x, StringIO is a sub-module of io - from io import BytesIO - from sys import maxsize as maxint - - iter_range = range - - def is_native_int(x): - return isinstance(x, int) - - def is_string(x): - return isinstance(x, str) - - from abc import ABC - - FileNotFoundError = FileNotFoundError - - -def _copy_bytes(start, end, seq): - """Return an immutable copy of a sequence (byte string, byte array, memoryview) - in a certain interval [start:seq]""" - - if isinstance(seq, memoryview): - return seq[start:end].tobytes() - elif isinstance(seq, bytearray): - return bytes(seq[start:end]) - else: - return seq[start:end] - -del sys -del abc diff --git a/Crypto/Util/py3compat.pyi b/Crypto/Util/py3compat.pyi deleted file mode 100644 index 52de77f..0000000 --- a/Crypto/Util/py3compat.pyi +++ /dev/null @@ -1,31 +0,0 @@ -from typing import Union, Any, Optional, IO - -Buffer = Union[bytes, bytearray, memoryview] - -import sys - -def b(s: str) -> bytes: ... -def bchr(s: int) -> bytes: ... -def bord(s: bytes) -> int: ... -def tobytes(s: Union[bytes, str]) -> bytes: ... -def tostr(b: bytes) -> str: ... -def bytestring(x: Any) -> bool: ... - -def is_native_int(s: Any) -> bool: ... -def is_string(x: Any) -> bool: ... - -def BytesIO(b: bytes) -> IO[bytes]: ... - -if sys.version_info[0] == 2: - from sys import maxint - iter_range = xrange - -else: - from sys import maxsize as maxint - iter_range = range - -class FileNotFoundError: - def __init__(self, err: int, msg: str, filename: str) -> None: - pass - -def _copy_bytes(start: Optional[int], end: Optional[int], seq: Buffer) -> bytes: ... diff --git a/Crypto/Util/strxor.py b/Crypto/Util/strxor.py deleted file mode 100644 index 2bff250..0000000 --- a/Crypto/Util/strxor.py +++ /dev/null @@ -1,137 +0,0 @@ -# =================================================================== -# -# Copyright (c) 2014, Legrandin -# 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 Crypto.Util._raw_api import (load_pycryptodome_raw_lib, c_size_t, - create_string_buffer, get_raw_buffer, - c_uint8_ptr, is_writeable_buffer) - -_raw_strxor = load_pycryptodome_raw_lib("Crypto.Util._strxor", - """ - void strxor(const uint8_t *in1, - const uint8_t *in2, - uint8_t *out, size_t len); - void strxor_c(const uint8_t *in, - uint8_t c, - uint8_t *out, - size_t len); - """) - - -def strxor(term1, term2, output=None): - """XOR two byte strings. - - Args: - term1 (bytes/bytearray/memoryview): - The first term of the XOR operation. - term2 (bytes/bytearray/memoryview): - The second term of the XOR operation. - output (bytearray/memoryview): - The location where the result must be written to. - If ``None``, the result is returned. - :Return: - If ``output`` is ``None``, a new ``bytes`` string with the result. - Otherwise ``None``. - """ - - if len(term1) != len(term2): - raise ValueError("Only byte strings of equal length can be xored") - - if output is None: - result = create_string_buffer(len(term1)) - else: - # Note: output may overlap with either input - result = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(term1) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(term1)) - - _raw_strxor.strxor(c_uint8_ptr(term1), - c_uint8_ptr(term2), - c_uint8_ptr(result), - c_size_t(len(term1))) - - if output is None: - return get_raw_buffer(result) - else: - return None - - -def strxor_c(term, c, output=None): - """XOR a byte string with a repeated sequence of characters. - - Args: - term(bytes/bytearray/memoryview): - The first term of the XOR operation. - c (bytes): - The byte that makes up the second term of the XOR operation. - output (None or bytearray/memoryview): - If not ``None``, the location where the result is stored into. - - Return: - If ``output`` is ``None``, a new ``bytes`` string with the result. - Otherwise ``None``. - """ - - if not 0 <= c < 256: - raise ValueError("c must be in range(256)") - - if output is None: - result = create_string_buffer(len(term)) - else: - # Note: output may overlap with either input - result = output - - if not is_writeable_buffer(output): - raise TypeError("output must be a bytearray or a writeable memoryview") - - if len(term) != len(output): - raise ValueError("output must have the same length as the input" - " (%d bytes)" % len(term)) - - _raw_strxor.strxor_c(c_uint8_ptr(term), - c, - c_uint8_ptr(result), - c_size_t(len(term)) - ) - - if output is None: - return get_raw_buffer(result) - else: - return None - - -def _strxor_direct(term1, term2, result): - """Very fast XOR - check conditions!""" - _raw_strxor.strxor(term1, term2, result, c_size_t(len(term1))) - diff --git a/Crypto/Util/strxor.pyi b/Crypto/Util/strxor.pyi deleted file mode 100644 index ca896f3..0000000 --- a/Crypto/Util/strxor.pyi +++ /dev/null @@ -1,6 +0,0 @@ -from typing import Union, Optional - -Buffer = Union[bytes, bytearray, memoryview] - -def strxor(term1: bytes, term2: bytes, output: Optional[Buffer]=...) -> bytes: ... -def strxor_c(term: bytes, c: int, output: Optional[Buffer]=...) -> bytes: ... diff --git a/Crypto/__init__.py b/Crypto/__init__.py deleted file mode 100644 index e7713fe..0000000 --- a/Crypto/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -__all__ = ['Cipher', 'Hash', 'Protocol', 'PublicKey', 'Util', 'Signature', - 'IO', 'Math'] - -version_info = (3, 10, 1) - -__version__ = ".".join([str(x) for x in version_info]) diff --git a/Crypto/__init__.pyi b/Crypto/__init__.pyi deleted file mode 100644 index bc73446..0000000 --- a/Crypto/__init__.pyi +++ /dev/null @@ -1,4 +0,0 @@ -from typing import Tuple, Union - -version_info : Tuple[int, int, Union[int, str]] -__version__ : str diff --git a/Crypto/__pycache__/__init__.cpython-36.pyc b/Crypto/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index aa03a44..0000000 Binary files a/Crypto/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/Crypto/py.typed b/Crypto/py.typed deleted file mode 100644 index e69de29..0000000