Spaces:
Sleeping
Sleeping
# -*- 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) <ecb_mode>` | |
:var MODE_CBC: :ref:`Cipher-Block Chaining (CBC) <cbc_mode>` | |
:var MODE_CFB: :ref:`Cipher FeedBack (CFB) <cfb_mode>` | |
:var MODE_OFB: :ref:`Output FeedBack (OFB) <ofb_mode>` | |
:var MODE_CTR: :ref:`CounTer Mode (CTR) <ctr_mode>` | |
:var MODE_OPENPGP: :ref:`OpenPGP Mode <openpgp_mode>` | |
:var MODE_EAX: :ref:`EAX Mode <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) | |