uh oh im bundling the deps
This commit is contained in:
parent
ae28da8d60
commit
ecca301ceb
584 changed files with 119933 additions and 24 deletions
addon.xml
resources/lib/deps/Cryptodome
Cipher
AES.pyAES.pyiARC2.pyARC2.pyiARC4.pyARC4.pyiBlowfish.pyBlowfish.pyiCAST.pyCAST.pyiChaCha20.pyChaCha20.pyiChaCha20_Poly1305.pyChaCha20_Poly1305.pyiDES.pyDES.pyiDES3.pyDES3.pyiPKCS1_OAEP.pyPKCS1_OAEP.pyiPKCS1_v1_5.pyPKCS1_v1_5.pyiSalsa20.pySalsa20.pyi_ARC4.abi3.so_EKSBlowfish.py_EKSBlowfish.pyi_Salsa20.abi3.so__init__.py__init__.pyi_chacha20.abi3.so_mode_cbc.py_mode_cbc.pyi_mode_ccm.py_mode_ccm.pyi_mode_cfb.py_mode_cfb.pyi_mode_ctr.py_mode_ctr.pyi_mode_eax.py_mode_eax.pyi_mode_ecb.py_mode_ecb.pyi_mode_gcm.py_mode_gcm.pyi_mode_ocb.py_mode_ocb.pyi_mode_ofb.py_mode_ofb.pyi_mode_openpgp.py_mode_openpgp.pyi_mode_siv.py_mode_siv.pyi_pkcs1_decode.abi3.so_pkcs1_oaep_decode.py_raw_aes.abi3.so_raw_aesni.abi3.so_raw_arc2.abi3.so_raw_blowfish.abi3.so_raw_cast.abi3.so_raw_cbc.abi3.so_raw_cfb.abi3.so_raw_ctr.abi3.so_raw_des.abi3.so_raw_des3.abi3.so_raw_ecb.abi3.so_raw_eksblowfish.abi3.so_raw_ocb.abi3.so_raw_ofb.abi3.so
Hash
|
@ -1,5 +1,5 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<addon id="plugin.audio.librespot" version="0.0.1" name="Librespot" provider-name="Cere">
|
||||
<addon id="plugin.audio.librespot" version="0.0.2" name="Librespot" provider-name="Cere">
|
||||
<requires>
|
||||
<import addon="xbmc.python" version="3.0.0" />
|
||||
<import addon="xbmc.addon" version="18.9.701" />
|
||||
|
@ -20,8 +20,8 @@
|
|||
<summary lang="en_GB">Unofficial Spotify music plugin for Kodi</summary>
|
||||
<description lang="en_GB">Allows you to use your Spotify premium account to connect and play Spotify through Kodi. After installing, use 'Configure' to enter your Spotify username and password.</description>
|
||||
<disclaimer lang="en_GB">This product uses the SPOTIFY WEB API but is not endorsed, certified or otherwise approved in any way by Spotify. Spotify is the registered trademark of Spotify AB.</disclaimer>
|
||||
<source>https://example.com</source>
|
||||
<website>https://cere.gay</website>
|
||||
<source>https://gitdab.com/cere/plugin.audio.librespot</source>
|
||||
<website>https://gitdab.com/cere/</website>
|
||||
<news>Deez Nuts
|
||||
</news>
|
||||
<assets>
|
||||
|
|
234
resources/lib/deps/Cryptodome/Cipher/AES.py
Normal file
234
resources/lib/deps/Cryptodome/Cipher/AES.py
Normal file
|
@ -0,0 +1,234 @@
|
|||
# -*- 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.
|
||||
# ===================================================================
|
||||
|
||||
import sys
|
||||
|
||||
from Cryptodome.Cipher import _create_cipher
|
||||
from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||
VoidPointer, SmartPointer,
|
||||
c_size_t, c_uint8_ptr)
|
||||
|
||||
from Cryptodome.Util import _cpu_features
|
||||
from Cryptodome.Random import get_random_bytes
|
||||
|
||||
MODE_ECB = 1 #: Electronic Code Book (:ref:`ecb_mode`)
|
||||
MODE_CBC = 2 #: Cipher-Block Chaining (:ref:`cbc_mode`)
|
||||
MODE_CFB = 3 #: Cipher Feedback (:ref:`cfb_mode`)
|
||||
MODE_OFB = 5 #: Output Feedback (:ref:`ofb_mode`)
|
||||
MODE_CTR = 6 #: Counter mode (:ref:`ctr_mode`)
|
||||
MODE_OPENPGP = 7 #: OpenPGP mode (:ref:`openpgp_mode`)
|
||||
MODE_CCM = 8 #: Counter with CBC-MAC (:ref:`ccm_mode`)
|
||||
MODE_EAX = 9 #: :ref:`eax_mode`
|
||||
MODE_SIV = 10 #: Synthetic Initialization Vector (:ref:`siv_mode`)
|
||||
MODE_GCM = 11 #: Galois Counter Mode (:ref:`gcm_mode`)
|
||||
MODE_OCB = 12 #: Offset Code Book (:ref:`ocb_mode`)
|
||||
|
||||
|
||||
_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("Cryptodome.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("Cryptodome.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.
|
||||
|
||||
Args:
|
||||
key(bytes/bytearray/memoryview):
|
||||
The secret key to use in the symmetric cipher.
|
||||
|
||||
It must be 16 (*AES-128)*, 24 (*AES-192*) or 32 (*AES-256*) bytes long.
|
||||
|
||||
For ``MODE_SIV`` only, it doubles to 32, 48, or 64 bytes.
|
||||
mode (a ``MODE_*`` constant):
|
||||
The chaining mode to use for encryption or decryption.
|
||||
If in doubt, use ``MODE_EAX``.
|
||||
|
||||
Keyword Args:
|
||||
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):
|
||||
(Only ``MODE_CTR``).
|
||||
Instance of ``Cryptodome.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).
|
||||
|
||||
Returns:
|
||||
an AES object, of the applicable mode.
|
||||
"""
|
||||
|
||||
kwargs["add_aes_modes"] = True
|
||||
return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
|
||||
|
||||
|
||||
# Size of a data block (in bytes)
|
||||
block_size = 16
|
||||
# Size of a key (in bytes)
|
||||
key_size = (16, 24, 32)
|
156
resources/lib/deps/Cryptodome/Cipher/AES.pyi
Normal file
156
resources/lib/deps/Cryptodome/Cipher/AES.pyi
Normal file
|
@ -0,0 +1,156 @@
|
|||
from typing import Dict, Optional, Tuple, Union, overload
|
||||
from typing_extensions import Literal
|
||||
|
||||
Buffer=bytes|bytearray|memoryview
|
||||
|
||||
from Cryptodome.Cipher._mode_ecb import EcbMode
|
||||
from Cryptodome.Cipher._mode_cbc import CbcMode
|
||||
from Cryptodome.Cipher._mode_cfb import CfbMode
|
||||
from Cryptodome.Cipher._mode_ofb import OfbMode
|
||||
from Cryptodome.Cipher._mode_ctr import CtrMode
|
||||
from Cryptodome.Cipher._mode_openpgp import OpenPgpMode
|
||||
from Cryptodome.Cipher._mode_ccm import CcmMode
|
||||
from Cryptodome.Cipher._mode_eax import EaxMode
|
||||
from Cryptodome.Cipher._mode_gcm import GcmMode
|
||||
from Cryptodome.Cipher._mode_siv import SivMode
|
||||
from Cryptodome.Cipher._mode_ocb import OcbMode
|
||||
|
||||
MODE_ECB: Literal[1]
|
||||
MODE_CBC: Literal[2]
|
||||
MODE_CFB: Literal[3]
|
||||
MODE_OFB: Literal[5]
|
||||
MODE_CTR: Literal[6]
|
||||
MODE_OPENPGP: Literal[7]
|
||||
MODE_CCM: Literal[8]
|
||||
MODE_EAX: Literal[9]
|
||||
MODE_SIV: Literal[10]
|
||||
MODE_GCM: Literal[11]
|
||||
MODE_OCB: Literal[12]
|
||||
|
||||
# MODE_ECB
|
||||
@overload
|
||||
def new(key: Buffer,
|
||||
mode: Literal[1],
|
||||
use_aesni : bool = ...) -> \
|
||||
EcbMode: ...
|
||||
|
||||
# MODE_CBC
|
||||
@overload
|
||||
def new(key: Buffer,
|
||||
mode: Literal[2],
|
||||
iv : Optional[Buffer] = ...,
|
||||
use_aesni : bool = ...) -> \
|
||||
CbcMode: ...
|
||||
|
||||
@overload
|
||||
def new(key: Buffer,
|
||||
mode: Literal[2],
|
||||
IV : Optional[Buffer] = ...,
|
||||
use_aesni : bool = ...) -> \
|
||||
CbcMode: ...
|
||||
|
||||
# MODE_CFB
|
||||
@overload
|
||||
def new(key: Buffer,
|
||||
mode: Literal[3],
|
||||
iv : Optional[Buffer] = ...,
|
||||
segment_size : int = ...,
|
||||
use_aesni : bool = ...) -> \
|
||||
CfbMode: ...
|
||||
|
||||
@overload
|
||||
def new(key: Buffer,
|
||||
mode: Literal[3],
|
||||
IV : Optional[Buffer] = ...,
|
||||
segment_size : int = ...,
|
||||
use_aesni : bool = ...) -> \
|
||||
CfbMode: ...
|
||||
|
||||
# MODE_OFB
|
||||
@overload
|
||||
def new(key: Buffer,
|
||||
mode: Literal[5],
|
||||
iv : Optional[Buffer] = ...,
|
||||
use_aesni : bool = ...) -> \
|
||||
OfbMode: ...
|
||||
|
||||
@overload
|
||||
def new(key: Buffer,
|
||||
mode: Literal[5],
|
||||
IV : Optional[Buffer] = ...,
|
||||
use_aesni : bool = ...) -> \
|
||||
OfbMode: ...
|
||||
|
||||
# MODE_CTR
|
||||
@overload
|
||||
def new(key: Buffer,
|
||||
mode: Literal[6],
|
||||
nonce : Optional[Buffer] = ...,
|
||||
initial_value : Union[int, Buffer] = ...,
|
||||
counter : Dict = ...,
|
||||
use_aesni : bool = ...) -> \
|
||||
CtrMode: ...
|
||||
|
||||
# MODE_OPENPGP
|
||||
@overload
|
||||
def new(key: Buffer,
|
||||
mode: Literal[7],
|
||||
iv : Optional[Buffer] = ...,
|
||||
use_aesni : bool = ...) -> \
|
||||
OpenPgpMode: ...
|
||||
|
||||
@overload
|
||||
def new(key: Buffer,
|
||||
mode: Literal[7],
|
||||
IV : Optional[Buffer] = ...,
|
||||
use_aesni : bool = ...) -> \
|
||||
OpenPgpMode: ...
|
||||
|
||||
# MODE_CCM
|
||||
@overload
|
||||
def new(key: Buffer,
|
||||
mode: Literal[8],
|
||||
nonce : Optional[Buffer] = ...,
|
||||
mac_len : int = ...,
|
||||
assoc_len : int = ...,
|
||||
use_aesni : bool = ...) -> \
|
||||
CcmMode: ...
|
||||
|
||||
# MODE_EAX
|
||||
@overload
|
||||
def new(key: Buffer,
|
||||
mode: Literal[9],
|
||||
nonce : Optional[Buffer] = ...,
|
||||
mac_len : int = ...,
|
||||
use_aesni : bool = ...) -> \
|
||||
EaxMode: ...
|
||||
|
||||
# MODE_GCM
|
||||
@overload
|
||||
def new(key: Buffer,
|
||||
mode: Literal[10],
|
||||
nonce : Optional[Buffer] = ...,
|
||||
use_aesni : bool = ...) -> \
|
||||
SivMode: ...
|
||||
|
||||
# MODE_SIV
|
||||
@overload
|
||||
def new(key: Buffer,
|
||||
mode: Literal[11],
|
||||
nonce : Optional[Buffer] = ...,
|
||||
mac_len : int = ...,
|
||||
use_aesni : bool = ...) -> \
|
||||
GcmMode: ...
|
||||
|
||||
# MODE_OCB
|
||||
@overload
|
||||
def new(key: Buffer,
|
||||
mode: Literal[12],
|
||||
nonce : Optional[Buffer] = ...,
|
||||
mac_len : int = ...,
|
||||
use_aesni : bool = ...) -> \
|
||||
OcbMode: ...
|
||||
|
||||
|
||||
block_size: int
|
||||
key_size: Tuple[int, int, int]
|
175
resources/lib/deps/Cryptodome/Cipher/ARC2.py
Normal file
175
resources/lib/deps/Cryptodome/Cipher/ARC2.py
Normal file
|
@ -0,0 +1,175 @@
|
|||
# -*- 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) <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 Cryptodome.Cipher import _create_cipher
|
||||
from Cryptodome.Util.py3compat import byte_string
|
||||
from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||
VoidPointer, SmartPointer,
|
||||
c_size_t, c_uint8_ptr)
|
||||
|
||||
_raw_arc2_lib = load_pycryptodome_raw_lib(
|
||||
"Cryptodome.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)
|
35
resources/lib/deps/Cryptodome/Cipher/ARC2.pyi
Normal file
35
resources/lib/deps/Cryptodome/Cipher/ARC2.pyi
Normal file
|
@ -0,0 +1,35 @@
|
|||
from typing import Union, Dict, Iterable, Optional
|
||||
|
||||
Buffer = bytes|bytearray|memoryview
|
||||
|
||||
from Cryptodome.Cipher._mode_ecb import EcbMode
|
||||
from Cryptodome.Cipher._mode_cbc import CbcMode
|
||||
from Cryptodome.Cipher._mode_cfb import CfbMode
|
||||
from Cryptodome.Cipher._mode_ofb import OfbMode
|
||||
from Cryptodome.Cipher._mode_ctr import CtrMode
|
||||
from Cryptodome.Cipher._mode_openpgp import OpenPgpMode
|
||||
from Cryptodome.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
|
||||
|
||||
def new(key: Buffer,
|
||||
mode: ARC2Mode,
|
||||
iv : Optional[Buffer] = ...,
|
||||
IV : Optional[Buffer] = ...,
|
||||
nonce : Optional[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]
|
136
resources/lib/deps/Cryptodome/Cipher/ARC4.py
Normal file
136
resources/lib/deps/Cryptodome/Cipher/ARC4.py
Normal file
|
@ -0,0 +1,136 @@
|
|||
# -*- 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 Cryptodome.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("Cryptodome.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:`Cryptodome.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 ``[1..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(1, 256+1)
|
16
resources/lib/deps/Cryptodome/Cipher/ARC4.pyi
Normal file
16
resources/lib/deps/Cryptodome/Cipher/ARC4.pyi
Normal file
|
@ -0,0 +1,16 @@
|
|||
from typing import Any, Union, Iterable
|
||||
|
||||
Buffer = 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]
|
159
resources/lib/deps/Cryptodome/Cipher/Blowfish.py
Normal file
159
resources/lib/deps/Cryptodome/Cipher/Blowfish.py
Normal file
|
@ -0,0 +1,159 @@
|
|||
# -*- 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) <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 Cryptodome.Cipher import _create_cipher
|
||||
from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||
VoidPointer, SmartPointer, c_size_t,
|
||||
c_uint8_ptr)
|
||||
|
||||
_raw_blowfish_lib = load_pycryptodome_raw_lib(
|
||||
"Cryptodome.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)
|
35
resources/lib/deps/Cryptodome/Cipher/Blowfish.pyi
Normal file
35
resources/lib/deps/Cryptodome/Cipher/Blowfish.pyi
Normal file
|
@ -0,0 +1,35 @@
|
|||
from typing import Union, Dict, Iterable, Optional
|
||||
|
||||
Buffer = bytes|bytearray|memoryview
|
||||
|
||||
from Cryptodome.Cipher._mode_ecb import EcbMode
|
||||
from Cryptodome.Cipher._mode_cbc import CbcMode
|
||||
from Cryptodome.Cipher._mode_cfb import CfbMode
|
||||
from Cryptodome.Cipher._mode_ofb import OfbMode
|
||||
from Cryptodome.Cipher._mode_ctr import CtrMode
|
||||
from Cryptodome.Cipher._mode_openpgp import OpenPgpMode
|
||||
from Cryptodome.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
|
||||
|
||||
def new(key: Buffer,
|
||||
mode: BlowfishMode,
|
||||
iv : Optional[Buffer] = ...,
|
||||
IV : Optional[Buffer] = ...,
|
||||
nonce : Optional[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]
|
159
resources/lib/deps/Cryptodome/Cipher/CAST.py
Normal file
159
resources/lib/deps/Cryptodome/Cipher/CAST.py
Normal file
|
@ -0,0 +1,159 @@
|
|||
# -*- 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) <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 Cryptodome.Cipher import _create_cipher
|
||||
from Cryptodome.Util.py3compat import byte_string
|
||||
from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||
VoidPointer, SmartPointer,
|
||||
c_size_t, c_uint8_ptr)
|
||||
|
||||
_raw_cast_lib = load_pycryptodome_raw_lib(
|
||||
"Cryptodome.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)
|
35
resources/lib/deps/Cryptodome/Cipher/CAST.pyi
Normal file
35
resources/lib/deps/Cryptodome/Cipher/CAST.pyi
Normal file
|
@ -0,0 +1,35 @@
|
|||
from typing import Union, Dict, Iterable, Optional
|
||||
|
||||
Buffer = bytes|bytearray|memoryview
|
||||
|
||||
from Cryptodome.Cipher._mode_ecb import EcbMode
|
||||
from Cryptodome.Cipher._mode_cbc import CbcMode
|
||||
from Cryptodome.Cipher._mode_cfb import CfbMode
|
||||
from Cryptodome.Cipher._mode_ofb import OfbMode
|
||||
from Cryptodome.Cipher._mode_ctr import CtrMode
|
||||
from Cryptodome.Cipher._mode_openpgp import OpenPgpMode
|
||||
from Cryptodome.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
|
||||
|
||||
def new(key: Buffer,
|
||||
mode: CASTMode,
|
||||
iv : Optional[Buffer] = ...,
|
||||
IV : Optional[Buffer] = ...,
|
||||
nonce : Optional[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]
|
287
resources/lib/deps/Cryptodome/Cipher/ChaCha20.py
Normal file
287
resources/lib/deps/Cryptodome/Cipher/ChaCha20.py
Normal file
|
@ -0,0 +1,287 @@
|
|||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
from Cryptodome.Random import get_random_bytes
|
||||
|
||||
from Cryptodome.Util.py3compat import _copy_bytes
|
||||
from Cryptodome.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("Cryptodome.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 = ("encrypt", "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 "encrypt" not in self._next:
|
||||
raise TypeError("Cipher object can only be used for decryption")
|
||||
self._next = ("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 "decrypt" not in self._next:
|
||||
raise TypeError("Cipher object can only be used for encryption")
|
||||
self._next = ("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:`Cryptodome.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
|
25
resources/lib/deps/Cryptodome/Cipher/ChaCha20.pyi
Normal file
25
resources/lib/deps/Cryptodome/Cipher/ChaCha20.pyi
Normal file
|
@ -0,0 +1,25 @@
|
|||
from typing import Union, overload, Optional
|
||||
|
||||
Buffer = 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: Optional[Buffer] = ...) -> ChaCha20Cipher: ...
|
||||
|
||||
block_size: int
|
||||
key_size: int
|
336
resources/lib/deps/Cryptodome/Cipher/ChaCha20_Poly1305.py
Normal file
336
resources/lib/deps/Cryptodome/Cipher/ChaCha20_Poly1305.py
Normal file
|
@ -0,0 +1,336 @@
|
|||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2018, Helder Eijs <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
from binascii import unhexlify
|
||||
|
||||
from Cryptodome.Cipher import ChaCha20
|
||||
from Cryptodome.Cipher.ChaCha20 import _HChaCha20
|
||||
from Cryptodome.Hash import Poly1305, BLAKE2s
|
||||
|
||||
from Cryptodome.Random import get_random_bytes
|
||||
|
||||
from Cryptodome.Util.number import long_to_bytes
|
||||
from Cryptodome.Util.py3compat import _copy_bytes, bord
|
||||
from Cryptodome.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._next = ("update", "encrypt", "decrypt", "digest",
|
||||
"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 "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 "encrypt" not in self._next:
|
||||
raise TypeError("encrypt() method cannot be called")
|
||||
|
||||
if self._status == _CipherStatus.PROCESSING_AUTH_DATA:
|
||||
self._pad_aad()
|
||||
|
||||
self._next = ("encrypt", "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 "decrypt" not in self._next:
|
||||
raise TypeError("decrypt() method cannot be called")
|
||||
|
||||
if self._status == _CipherStatus.PROCESSING_AUTH_DATA:
|
||||
self._pad_aad()
|
||||
|
||||
self._next = ("decrypt", "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 "digest" not in self._next:
|
||||
raise TypeError("digest() method cannot be called")
|
||||
self._next = ("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 "verify" not in self._next:
|
||||
raise TypeError("verify() cannot be called"
|
||||
" when encrypting a message")
|
||||
self._next = ("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:`Cryptodome.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):
|
||||
chacha20_poly1305_nonce = nonce
|
||||
elif len(nonce) == 24:
|
||||
key = _HChaCha20(key, nonce[:16])
|
||||
chacha20_poly1305_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))
|
||||
|
||||
cipher = ChaCha20Poly1305Cipher(key, chacha20_poly1305_nonce)
|
||||
cipher.nonce = _copy_bytes(None, None, nonce)
|
||||
return cipher
|
||||
|
||||
|
||||
# Size of a key (in bytes)
|
||||
key_size = 32
|
28
resources/lib/deps/Cryptodome/Cipher/ChaCha20_Poly1305.pyi
Normal file
28
resources/lib/deps/Cryptodome/Cipher/ChaCha20_Poly1305.pyi
Normal file
|
@ -0,0 +1,28 @@
|
|||
from typing import Union, Tuple, overload, Optional
|
||||
|
||||
Buffer = 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: Optional[Buffer] = ...) -> ChaCha20Poly1305Cipher: ...
|
||||
|
||||
block_size: int
|
||||
key_size: int
|
158
resources/lib/deps/Cryptodome/Cipher/DES.py
Normal file
158
resources/lib/deps/Cryptodome/Cipher/DES.py
Normal file
|
@ -0,0 +1,158 @@
|
|||
# -*- 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) <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 Cryptodome.Cipher import _create_cipher
|
||||
from Cryptodome.Util.py3compat import byte_string
|
||||
from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||
VoidPointer, SmartPointer,
|
||||
c_size_t, c_uint8_ptr)
|
||||
|
||||
_raw_des_lib = load_pycryptodome_raw_lib(
|
||||
"Cryptodome.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
|
35
resources/lib/deps/Cryptodome/Cipher/DES.pyi
Normal file
35
resources/lib/deps/Cryptodome/Cipher/DES.pyi
Normal file
|
@ -0,0 +1,35 @@
|
|||
from typing import Union, Dict, Iterable, Optional
|
||||
|
||||
Buffer = bytes|bytearray|memoryview
|
||||
|
||||
from Cryptodome.Cipher._mode_ecb import EcbMode
|
||||
from Cryptodome.Cipher._mode_cbc import CbcMode
|
||||
from Cryptodome.Cipher._mode_cfb import CfbMode
|
||||
from Cryptodome.Cipher._mode_ofb import OfbMode
|
||||
from Cryptodome.Cipher._mode_ctr import CtrMode
|
||||
from Cryptodome.Cipher._mode_openpgp import OpenPgpMode
|
||||
from Cryptodome.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
|
||||
|
||||
def new(key: Buffer,
|
||||
mode: DESMode,
|
||||
iv : Optional[Buffer] = ...,
|
||||
IV : Optional[Buffer] = ...,
|
||||
nonce : Optional[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
|
187
resources/lib/deps/Cryptodome/Cipher/DES3.py
Normal file
187
resources/lib/deps/Cryptodome/Cipher/DES3.py
Normal file
|
@ -0,0 +1,187 @@
|
|||
# -*- 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 Cryptodome.Cipher import _create_cipher
|
||||
from Cryptodome.Util.py3compat import byte_string, bchr, bord, bstr
|
||||
from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||
VoidPointer, SmartPointer,
|
||||
c_size_t)
|
||||
|
||||
_raw_des3_lib = load_pycryptodome_raw_lib(
|
||||
"Cryptodome.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)
|
37
resources/lib/deps/Cryptodome/Cipher/DES3.pyi
Normal file
37
resources/lib/deps/Cryptodome/Cipher/DES3.pyi
Normal file
|
@ -0,0 +1,37 @@
|
|||
from typing import Union, Dict, Tuple, Optional
|
||||
|
||||
Buffer = bytes|bytearray|memoryview
|
||||
|
||||
from Cryptodome.Cipher._mode_ecb import EcbMode
|
||||
from Cryptodome.Cipher._mode_cbc import CbcMode
|
||||
from Cryptodome.Cipher._mode_cfb import CfbMode
|
||||
from Cryptodome.Cipher._mode_ofb import OfbMode
|
||||
from Cryptodome.Cipher._mode_ctr import CtrMode
|
||||
from Cryptodome.Cipher._mode_openpgp import OpenPgpMode
|
||||
from Cryptodome.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
|
||||
|
||||
def new(key: Buffer,
|
||||
mode: DES3Mode,
|
||||
iv : Optional[Buffer] = ...,
|
||||
IV : Optional[Buffer] = ...,
|
||||
nonce : Optional[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]
|
231
resources/lib/deps/Cryptodome/Cipher/PKCS1_OAEP.py
Normal file
231
resources/lib/deps/Cryptodome/Cipher/PKCS1_OAEP.py
Normal file
|
@ -0,0 +1,231 @@
|
|||
# -*- 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 Cryptodome.Signature.pss import MGF1
|
||||
import Cryptodome.Hash.SHA1
|
||||
|
||||
from Cryptodome.Util.py3compat import _copy_bytes
|
||||
import Cryptodome.Util.number
|
||||
from Cryptodome.Util.number import ceil_div, bytes_to_long, long_to_bytes
|
||||
from Cryptodome.Util.strxor import strxor
|
||||
from Cryptodome import Random
|
||||
from ._pkcs1_oaep_decode import oaep_decode
|
||||
|
||||
|
||||
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 `Cryptodome.Hash`
|
||||
or an existing hash object created from any of such modules. If not specified,
|
||||
`Cryptodome.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 = Cryptodome.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 = Cryptodome.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 = Cryptodome.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 < hLen+2:
|
||||
raise ValueError("Ciphertext with incorrect length.")
|
||||
# Step 2a (O2SIP)
|
||||
ct_int = bytes_to_long(ciphertext)
|
||||
# Step 2b (RSADP) and step 2c (I2OSP)
|
||||
em = self._key._decrypt_to_bytes(ct_int)
|
||||
# Step 3a
|
||||
lHash = self._hashObj.new(self._label).digest()
|
||||
# y must be 0, but we MUST NOT check it here in order not to
|
||||
# allow attacks like Manger's (http://dl.acm.org/citation.cfm?id=704143)
|
||||
maskedSeed = em[1:hLen+1]
|
||||
maskedDB = em[hLen+1:]
|
||||
# Step 3c
|
||||
seedMask = self._mgf(maskedDB, hLen)
|
||||
# Step 3d
|
||||
seed = strxor(maskedSeed, seedMask)
|
||||
# Step 3e
|
||||
dbMask = self._mgf(seed, k-hLen-1)
|
||||
# Step 3f
|
||||
db = strxor(maskedDB, dbMask)
|
||||
# Step 3b + 3g
|
||||
res = oaep_decode(em, lHash, db)
|
||||
if res <= 0:
|
||||
raise ValueError("Incorrect decryption.")
|
||||
# Step 4
|
||||
return db[res:]
|
||||
|
||||
|
||||
def new(key, hashAlgo=None, mgfunc=None, label=b'', randfunc=None):
|
||||
"""Return a cipher object :class:`PKCS1OAEP_Cipher`
|
||||
that can be used to perform PKCS#1 OAEP encryption or decryption.
|
||||
|
||||
:param key:
|
||||
The key object to use to encrypt or decrypt the message.
|
||||
Decryption is only possible with a private RSA key.
|
||||
:type key: RSA key object
|
||||
|
||||
:param hashAlgo:
|
||||
The hash function to use. This can be a module under `Cryptodome.Hash`
|
||||
or an existing hash object created from any of such modules.
|
||||
If not specified, `Cryptodome.Hash.SHA1` is used.
|
||||
:type hashAlgo: hash object
|
||||
|
||||
:param mgfunc:
|
||||
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).
|
||||
:type mgfunc: callable
|
||||
|
||||
:param label:
|
||||
A label to apply to this particular encryption. If not specified,
|
||||
an empty string is used. Specifying a label does not improve
|
||||
security.
|
||||
:type label: bytes/bytearray/memoryview
|
||||
|
||||
:param randfunc:
|
||||
A function that returns random bytes.
|
||||
The default is `Random.get_random_bytes`.
|
||||
:type randfunc: callable
|
||||
"""
|
||||
|
||||
if randfunc is None:
|
||||
randfunc = Random.get_random_bytes
|
||||
return PKCS1OAEP_Cipher(key, hashAlgo, mgfunc, label, randfunc)
|
35
resources/lib/deps/Cryptodome/Cipher/PKCS1_OAEP.pyi
Normal file
35
resources/lib/deps/Cryptodome/Cipher/PKCS1_OAEP.pyi
Normal file
|
@ -0,0 +1,35 @@
|
|||
from typing import Optional, Union, Callable, Any, overload
|
||||
from typing_extensions import Protocol
|
||||
|
||||
from Cryptodome.PublicKey.RSA import RsaKey
|
||||
|
||||
class HashLikeClass(Protocol):
|
||||
digest_size : int
|
||||
def new(self, data: Optional[bytes] = ...) -> 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: ...
|
189
resources/lib/deps/Cryptodome/Cipher/PKCS1_v1_5.py
Normal file
189
resources/lib/deps/Cryptodome/Cipher/PKCS1_v1_5.py
Normal file
|
@ -0,0 +1,189 @@
|
|||
# -*- 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 Cryptodome import Random
|
||||
from Cryptodome.Util.number import bytes_to_long, long_to_bytes
|
||||
from Cryptodome.Util.py3compat import bord, is_bytes, _copy_bytes
|
||||
from ._pkcs1_oaep_decode import pkcs1_decode
|
||||
|
||||
|
||||
class PKCS115_Cipher:
|
||||
"""This cipher can perform PKCS#1 v1.5 RSA encryption or decryption.
|
||||
Do not instantiate directly. Use :func:`Cryptodome.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
|
||||
<https://tools.ietf.org/html/rfc8017#page-28>`_.
|
||||
|
||||
: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
|
||||
k = self._key.size_in_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)
|
||||
# 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, expected_pt_len=0):
|
||||
r"""Decrypt a PKCS#1 v1.5 ciphertext.
|
||||
|
||||
This is the function ``RSAES-PKCS1-V1_5-DECRYPT`` specified in
|
||||
`section 7.2.2 of RFC8017
|
||||
<https://tools.ietf.org/html/rfc8017#page-29>`_.
|
||||
|
||||
Args:
|
||||
ciphertext (bytes/bytearray/memoryview):
|
||||
The ciphertext that contains the message to recover.
|
||||
sentinel (any type):
|
||||
The object to return whenever an error is detected.
|
||||
expected_pt_len (integer):
|
||||
The length the plaintext is known to have, or 0 if unknown.
|
||||
|
||||
Returns (byte string):
|
||||
It is either the original message or the ``sentinel`` (in case of an error).
|
||||
|
||||
.. warning::
|
||||
PKCS#1 v1.5 decryption is intrinsically vulnerable to timing
|
||||
attacks (see `Bleichenbacher's`__ attack).
|
||||
**Use PKCS#1 OAEP instead**.
|
||||
|
||||
This implementation attempts to mitigate the risk
|
||||
with some constant-time constructs.
|
||||
However, they are not sufficient by themselves: the type of protocol you
|
||||
implement and the way you handle errors make a big difference.
|
||||
|
||||
Specifically, you should make it very hard for the (malicious)
|
||||
party that submitted the ciphertext to quickly understand if decryption
|
||||
succeeded or not.
|
||||
|
||||
To this end, it is recommended that your protocol only encrypts
|
||||
plaintexts of fixed length (``expected_pt_len``),
|
||||
that ``sentinel`` is a random byte string of the same length,
|
||||
and that processing continues for as long
|
||||
as possible even if ``sentinel`` is returned (i.e. in case of
|
||||
incorrect decryption).
|
||||
|
||||
.. __: https://dx.doi.org/10.1007/BFb0055716
|
||||
"""
|
||||
|
||||
# See 7.2.2 in RFC8017
|
||||
k = self._key.size_in_bytes()
|
||||
|
||||
# Step 1
|
||||
if len(ciphertext) != k:
|
||||
raise ValueError("Ciphertext with incorrect length (not %d bytes)" % k)
|
||||
|
||||
# Step 2a (O2SIP)
|
||||
ct_int = bytes_to_long(ciphertext)
|
||||
|
||||
# Step 2b (RSADP) and Step 2c (I2OSP)
|
||||
em = self._key._decrypt_to_bytes(ct_int)
|
||||
|
||||
# Step 3 (not constant time when the sentinel is not a byte string)
|
||||
output = bytes(bytearray(k))
|
||||
if not is_bytes(sentinel) or len(sentinel) > k:
|
||||
size = pkcs1_decode(em, b'', expected_pt_len, output)
|
||||
if size < 0:
|
||||
return sentinel
|
||||
else:
|
||||
return output[size:]
|
||||
|
||||
# Step 3 (somewhat constant time)
|
||||
size = pkcs1_decode(em, sentinel, expected_pt_len, output)
|
||||
return output[size:]
|
||||
|
||||
|
||||
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 `Cryptodome.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:`Cryptodome.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)
|
20
resources/lib/deps/Cryptodome/Cipher/PKCS1_v1_5.pyi
Normal file
20
resources/lib/deps/Cryptodome/Cipher/PKCS1_v1_5.pyi
Normal file
|
@ -0,0 +1,20 @@
|
|||
from typing import Callable, Union, Any, Optional, TypeVar
|
||||
|
||||
from Cryptodome.PublicKey.RSA import RsaKey
|
||||
|
||||
Buffer = Union[bytes, bytearray, memoryview]
|
||||
T = TypeVar('T')
|
||||
|
||||
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: T,
|
||||
expected_pt_len: Optional[int] = ...) -> Union[bytes, T]: ...
|
||||
|
||||
def new(key: RsaKey,
|
||||
randfunc: Optional[Callable[[int], bytes]] = ...) -> PKCS115_Cipher: ...
|
167
resources/lib/deps/Cryptodome/Cipher/Salsa20.py
Normal file
167
resources/lib/deps/Cryptodome/Cipher/Salsa20.py
Normal file
|
@ -0,0 +1,167 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Cipher/Salsa20.py : Salsa20 stream cipher (http://cr.yp.to/snuffle.html)
|
||||
#
|
||||
# Contributed by Fabrizio Tarizzo <fabrizio@fabriziotarizzo.org>.
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
from Cryptodome.Util.py3compat import _copy_bytes
|
||||
from Cryptodome.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 Cryptodome.Random import get_random_bytes
|
||||
|
||||
_raw_salsa20_lib = load_pycryptodome_raw_lib("Cryptodome.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:`Cryptodome.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)
|
||||
|
26
resources/lib/deps/Cryptodome/Cipher/Salsa20.pyi
Normal file
26
resources/lib/deps/Cryptodome/Cipher/Salsa20.pyi
Normal file
|
@ -0,0 +1,26 @@
|
|||
from typing import Union, Tuple, Optional, overload, Optional
|
||||
|
||||
Buffer = 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]
|
||||
|
BIN
resources/lib/deps/Cryptodome/Cipher/_ARC4.abi3.so
Executable file
BIN
resources/lib/deps/Cryptodome/Cipher/_ARC4.abi3.so
Executable file
Binary file not shown.
131
resources/lib/deps/Cryptodome/Cipher/_EKSBlowfish.py
Normal file
131
resources/lib/deps/Cryptodome/Cipher/_EKSBlowfish.py
Normal file
|
@ -0,0 +1,131 @@
|
|||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2019, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
import sys
|
||||
|
||||
from Cryptodome.Cipher import _create_cipher
|
||||
from Cryptodome.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(
|
||||
"Cryptodome.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 <https://www.usenix.org/legacy/events/usenix99/provos/provos_html/node4.html>`_.
|
||||
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)
|
15
resources/lib/deps/Cryptodome/Cipher/_EKSBlowfish.pyi
Normal file
15
resources/lib/deps/Cryptodome/Cipher/_EKSBlowfish.pyi
Normal file
|
@ -0,0 +1,15 @@
|
|||
from typing import Union, Iterable
|
||||
|
||||
from Cryptodome.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]
|
BIN
resources/lib/deps/Cryptodome/Cipher/_Salsa20.abi3.so
Executable file
BIN
resources/lib/deps/Cryptodome/Cipher/_Salsa20.abi3.so
Executable file
Binary file not shown.
79
resources/lib/deps/Cryptodome/Cipher/__init__.py
Normal file
79
resources/lib/deps/Cryptodome/Cipher/__init__.py
Normal file
|
@ -0,0 +1,79 @@
|
|||
#
|
||||
# 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 Cryptodome.Cipher._mode_ecb import _create_ecb_cipher
|
||||
from Cryptodome.Cipher._mode_cbc import _create_cbc_cipher
|
||||
from Cryptodome.Cipher._mode_cfb import _create_cfb_cipher
|
||||
from Cryptodome.Cipher._mode_ofb import _create_ofb_cipher
|
||||
from Cryptodome.Cipher._mode_ctr import _create_ctr_cipher
|
||||
from Cryptodome.Cipher._mode_openpgp import _create_openpgp_cipher
|
||||
from Cryptodome.Cipher._mode_ccm import _create_ccm_cipher
|
||||
from Cryptodome.Cipher._mode_eax import _create_eax_cipher
|
||||
from Cryptodome.Cipher._mode_siv import _create_siv_cipher
|
||||
from Cryptodome.Cipher._mode_gcm import _create_gcm_cipher
|
||||
from Cryptodome.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)
|
BIN
resources/lib/deps/Cryptodome/Cipher/_chacha20.abi3.so
Executable file
BIN
resources/lib/deps/Cryptodome/Cipher/_chacha20.abi3.so
Executable file
Binary file not shown.
293
resources/lib/deps/Cryptodome/Cipher/_mode_cbc.py
Normal file
293
resources/lib/deps/Cryptodome/Cipher/_mode_cbc.py
Normal file
|
@ -0,0 +1,293 @@
|
|||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
"""
|
||||
Ciphertext Block Chaining (CBC) mode.
|
||||
"""
|
||||
|
||||
__all__ = ['CbcMode']
|
||||
|
||||
from Cryptodome.Util.py3compat import _copy_bytes
|
||||
from Cryptodome.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 Cryptodome.Random import get_random_bytes
|
||||
|
||||
raw_cbc_lib = load_pycryptodome_raw_lib("Cryptodome.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 = ["encrypt", "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 "encrypt" not in self._next:
|
||||
raise TypeError("encrypt() cannot be called after decrypt()")
|
||||
self._next = ["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 "decrypt" not in self._next:
|
||||
raise TypeError("decrypt() cannot be called after encrypt()")
|
||||
self._next = ["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 ``Cryptodome.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)
|
25
resources/lib/deps/Cryptodome/Cipher/_mode_cbc.pyi
Normal file
25
resources/lib/deps/Cryptodome/Cipher/_mode_cbc.pyi
Normal file
|
@ -0,0 +1,25 @@
|
|||
from typing import Union, overload
|
||||
|
||||
from Cryptodome.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: ...
|
||||
|
650
resources/lib/deps/Cryptodome/Cipher/_mode_ccm.py
Normal file
650
resources/lib/deps/Cryptodome/Cipher/_mode_ccm.py
Normal file
|
@ -0,0 +1,650 @@
|
|||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
"""
|
||||
Counter with CBC-MAC (CCM) mode.
|
||||
"""
|
||||
|
||||
__all__ = ['CcmMode']
|
||||
|
||||
import struct
|
||||
from binascii import unhexlify
|
||||
|
||||
from Cryptodome.Util.py3compat import (byte_string, bord,
|
||||
_copy_bytes)
|
||||
from Cryptodome.Util._raw_api import is_writeable_buffer
|
||||
|
||||
from Cryptodome.Util.strxor import strxor
|
||||
from Cryptodome.Util.number import long_to_bytes
|
||||
|
||||
from Cryptodome.Hash import BLAKE2s
|
||||
from Cryptodome.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 = ["update", "encrypt", "decrypt",
|
||||
"digest", "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 "update" not in self._next:
|
||||
raise TypeError("update() can only be called"
|
||||
" immediately after initialization")
|
||||
|
||||
self._next = ["update", "encrypt", "decrypt",
|
||||
"digest", "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 "encrypt" not in self._next:
|
||||
raise TypeError("encrypt() can only be called after"
|
||||
" initialization or an update()")
|
||||
self._next = ["encrypt", "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 = ["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 "decrypt" not in self._next:
|
||||
raise TypeError("decrypt() can only be called"
|
||||
" after initialization or an update()")
|
||||
self._next = ["decrypt", "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 = ["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 "digest" not in self._next:
|
||||
raise TypeError("digest() cannot be called when decrypting"
|
||||
" or validating a message")
|
||||
self._next = ["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 "verify" not in self._next:
|
||||
raise TypeError("verify() cannot be called"
|
||||
" when encrypting a message")
|
||||
self._next = ["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 `Cryptodome.Cipher` (like
|
||||
`Cryptodome.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)
|
47
resources/lib/deps/Cryptodome/Cipher/_mode_ccm.pyi
Normal file
47
resources/lib/deps/Cryptodome/Cipher/_mode_ccm.pyi
Normal file
|
@ -0,0 +1,47 @@
|
|||
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: ...
|
293
resources/lib/deps/Cryptodome/Cipher/_mode_cfb.py
Normal file
293
resources/lib/deps/Cryptodome/Cipher/_mode_cfb.py
Normal file
|
@ -0,0 +1,293 @@
|
|||
# -*- 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 Cryptodome.Util.py3compat import _copy_bytes
|
||||
from Cryptodome.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 Cryptodome.Random import get_random_bytes
|
||||
|
||||
raw_cfb_lib = load_pycryptodome_raw_lib("Cryptodome.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 = ["encrypt", "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 "encrypt" not in self._next:
|
||||
raise TypeError("encrypt() cannot be called after decrypt()")
|
||||
self._next = ["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 "decrypt" not in self._next:
|
||||
raise TypeError("decrypt() cannot be called after encrypt()")
|
||||
self._next = ["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 ``Cryptodome.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)
|
26
resources/lib/deps/Cryptodome/Cipher/_mode_cfb.pyi
Normal file
26
resources/lib/deps/Cryptodome/Cipher/_mode_cfb.pyi
Normal file
|
@ -0,0 +1,26 @@
|
|||
from typing import Union, overload
|
||||
|
||||
from Cryptodome.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: ...
|
393
resources/lib/deps/Cryptodome/Cipher/_mode_ctr.py
Normal file
393
resources/lib/deps/Cryptodome/Cipher/_mode_ctr.py
Normal file
|
@ -0,0 +1,393 @@
|
|||
# -*- 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 Cryptodome.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 Cryptodome.Random import get_random_bytes
|
||||
from Cryptodome.Util.py3compat import _copy_bytes, is_native_int
|
||||
from Cryptodome.Util.number import long_to_bytes
|
||||
|
||||
raw_ctr_lib = load_pycryptodome_raw_lib("Cryptodome.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 = ["encrypt", "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 "encrypt" not in self._next:
|
||||
raise TypeError("encrypt() cannot be called after decrypt()")
|
||||
self._next = ["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 "decrypt" not in self._next:
|
||||
raise TypeError("decrypt() cannot be called after encrypt()")
|
||||
self._next = ["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 ``Cryptodome.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 ``Cryptodome.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:
|
||||
# Cryptodome.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
|
||||
|
||||
# Cryptodome.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 Cryptodome.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)
|
27
resources/lib/deps/Cryptodome/Cipher/_mode_ctr.pyi
Normal file
27
resources/lib/deps/Cryptodome/Cipher/_mode_ctr.pyi
Normal file
|
@ -0,0 +1,27 @@
|
|||
from typing import Union, overload
|
||||
|
||||
from Cryptodome.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: ...
|
||||
|
408
resources/lib/deps/Cryptodome/Cipher/_mode_eax.py
Normal file
408
resources/lib/deps/Cryptodome/Cipher/_mode_eax.py
Normal file
|
@ -0,0 +1,408 @@
|
|||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
"""
|
||||
EAX mode.
|
||||
"""
|
||||
|
||||
__all__ = ['EaxMode']
|
||||
|
||||
import struct
|
||||
from binascii import unhexlify
|
||||
|
||||
from Cryptodome.Util.py3compat import byte_string, bord, _copy_bytes
|
||||
|
||||
from Cryptodome.Util._raw_api import is_buffer
|
||||
|
||||
from Cryptodome.Util.strxor import strxor
|
||||
from Cryptodome.Util.number import long_to_bytes, bytes_to_long
|
||||
|
||||
from Cryptodome.Hash import CMAC, BLAKE2s
|
||||
from Cryptodome.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 = ["update", "encrypt", "decrypt",
|
||||
"digest", "verify"]
|
||||
|
||||
# MAC tag length
|
||||
if not (2 <= self._mac_len <= self.block_size):
|
||||
raise ValueError("'mac_len' must be at least 2 and not 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 "update" not in self._next:
|
||||
raise TypeError("update() can only be called"
|
||||
" immediately after initialization")
|
||||
|
||||
self._next = ["update", "encrypt", "decrypt",
|
||||
"digest", "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 "encrypt" not in self._next:
|
||||
raise TypeError("encrypt() can only be called after"
|
||||
" initialization or an update()")
|
||||
self._next = ["encrypt", "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 "decrypt" not in self._next:
|
||||
raise TypeError("decrypt() can only be called"
|
||||
" after initialization or an update()")
|
||||
self._next = ["decrypt", "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 "digest" not in self._next:
|
||||
raise TypeError("digest() cannot be called when decrypting"
|
||||
" or validating a message")
|
||||
self._next = ["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 "verify" not in self._next:
|
||||
raise TypeError("verify() cannot be called"
|
||||
" when encrypting a message")
|
||||
self._next = ["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 `Cryptodome.Cipher` (like
|
||||
`Cryptodome.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)
|
45
resources/lib/deps/Cryptodome/Cipher/_mode_eax.pyi
Normal file
45
resources/lib/deps/Cryptodome/Cipher/_mode_eax.pyi
Normal file
|
@ -0,0 +1,45 @@
|
|||
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: ...
|
220
resources/lib/deps/Cryptodome/Cipher/_mode_ecb.py
Normal file
220
resources/lib/deps/Cryptodome/Cipher/_mode_ecb.py
Normal file
|
@ -0,0 +1,220 @@
|
|||
# -*- 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 Cryptodome.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("Cryptodome.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 ``Cryptodome.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)
|
19
resources/lib/deps/Cryptodome/Cipher/_mode_ecb.pyi
Normal file
19
resources/lib/deps/Cryptodome/Cipher/_mode_ecb.pyi
Normal file
|
@ -0,0 +1,19 @@
|
|||
from typing import Union, overload
|
||||
|
||||
from Cryptodome.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: ...
|
||||
|
620
resources/lib/deps/Cryptodome/Cipher/_mode_gcm.py
Normal file
620
resources/lib/deps/Cryptodome/Cipher/_mode_gcm.py
Normal file
|
@ -0,0 +1,620 @@
|
|||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
"""
|
||||
Galois/Counter Mode (GCM).
|
||||
"""
|
||||
|
||||
__all__ = ['GcmMode']
|
||||
|
||||
from binascii import unhexlify
|
||||
|
||||
from Cryptodome.Util.py3compat import bord, _copy_bytes
|
||||
|
||||
from Cryptodome.Util._raw_api import is_buffer
|
||||
|
||||
from Cryptodome.Util.number import long_to_bytes, bytes_to_long
|
||||
from Cryptodome.Hash import BLAKE2s
|
||||
from Cryptodome.Random import get_random_bytes
|
||||
|
||||
from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer,
|
||||
create_string_buffer, get_raw_buffer,
|
||||
SmartPointer, c_size_t, c_uint8_ptr)
|
||||
|
||||
from Cryptodome.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("Cryptodome.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("Cryptodome.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 = ["update", "encrypt", "decrypt",
|
||||
"digest", "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(self.nonce) % 16)) % 16 + 8
|
||||
ghash_in = (self.nonce +
|
||||
b'\x00' * fill +
|
||||
long_to_bytes(8 * len(self.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 "update" not in self._next:
|
||||
raise TypeError("update() can only be called"
|
||||
" immediately after initialization")
|
||||
|
||||
self._next = ["update", "encrypt", "decrypt",
|
||||
"digest", "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 "encrypt" not in self._next:
|
||||
raise TypeError("encrypt() can only be called after"
|
||||
" initialization or an update()")
|
||||
self._next = ["encrypt", "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 "decrypt" not in self._next:
|
||||
raise TypeError("decrypt() can only be called"
|
||||
" after initialization or an update()")
|
||||
self._next = ["decrypt", "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 "digest" not in self._next:
|
||||
raise TypeError("digest() cannot be called when decrypting"
|
||||
" or validating a message")
|
||||
self._next = ["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 "verify" not in self._next:
|
||||
raise TypeError("verify() cannot be called"
|
||||
" when encrypting a message")
|
||||
self._next = ["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 `Cryptodome.Cipher`.
|
||||
The cipher must have block length of 16 bytes.
|
||||
GCM has been only defined for `Cryptodome.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)
|
45
resources/lib/deps/Cryptodome/Cipher/_mode_gcm.pyi
Normal file
45
resources/lib/deps/Cryptodome/Cipher/_mode_gcm.pyi
Normal file
|
@ -0,0 +1,45 @@
|
|||
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: ...
|
532
resources/lib/deps/Cryptodome/Cipher/_mode_ocb.py
Normal file
532
resources/lib/deps/Cryptodome/Cipher/_mode_ocb.py
Normal file
|
@ -0,0 +1,532 @@
|
|||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
"""
|
||||
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 Cryptodome.Cipher import AES
|
||||
>>> from Cryptodome.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 Cryptodome.Util.py3compat import bord, _copy_bytes, bchr
|
||||
from Cryptodome.Util.number import long_to_bytes, bytes_to_long
|
||||
from Cryptodome.Util.strxor import strxor
|
||||
|
||||
from Cryptodome.Hash import BLAKE2s
|
||||
from Cryptodome.Random import get_random_bytes
|
||||
|
||||
from Cryptodome.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("Cryptodome.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 = ["update", "encrypt", "decrypt",
|
||||
"digest", "verify"]
|
||||
|
||||
# Compute Offset_0
|
||||
params_without_key = dict(cipher_params)
|
||||
key = params_without_key.pop("key")
|
||||
|
||||
taglen_mod128 = (self._mac_len * 8) % 128
|
||||
if len(self.nonce) < 15:
|
||||
nonce = bchr(taglen_mod128 << 1) +\
|
||||
b'\x00' * (14 - len(nonce)) +\
|
||||
b'\x01' +\
|
||||
self.nonce
|
||||
else:
|
||||
nonce = bchr((taglen_mod128 << 1) | 0x01) +\
|
||||
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 "update" not in self._next:
|
||||
raise TypeError("update() can only be called"
|
||||
" immediately after initialization")
|
||||
|
||||
self._next = ["encrypt", "decrypt", "digest",
|
||||
"verify", "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 "encrypt" not in self._next:
|
||||
raise TypeError("encrypt() can only be called after"
|
||||
" initialization or an update()")
|
||||
|
||||
if plaintext is None:
|
||||
self._next = ["digest"]
|
||||
else:
|
||||
self._next = ["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 "decrypt" not in self._next:
|
||||
raise TypeError("decrypt() can only be called after"
|
||||
" initialization or an update()")
|
||||
|
||||
if ciphertext is None:
|
||||
self._next = ["verify"]
|
||||
else:
|
||||
self._next = ["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 "digest" not in self._next:
|
||||
raise TypeError("digest() cannot be called now for this cipher")
|
||||
|
||||
assert(len(self._cache_P) == 0)
|
||||
|
||||
self._next = ["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 "verify" not in self._next:
|
||||
raise TypeError("verify() cannot be called now for this cipher")
|
||||
|
||||
assert(len(self._cache_P) == 0)
|
||||
|
||||
self._next = ["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 `Cryptodome.Cipher`
|
||||
(like `Cryptodome.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)
|
36
resources/lib/deps/Cryptodome/Cipher/_mode_ocb.pyi
Normal file
36
resources/lib/deps/Cryptodome/Cipher/_mode_ocb.pyi
Normal file
|
@ -0,0 +1,36 @@
|
|||
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: ...
|
282
resources/lib/deps/Cryptodome/Cipher/_mode_ofb.py
Normal file
282
resources/lib/deps/Cryptodome/Cipher/_mode_ofb.py
Normal file
|
@ -0,0 +1,282 @@
|
|||
# -*- 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 Cryptodome.Util.py3compat import _copy_bytes
|
||||
from Cryptodome.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 Cryptodome.Random import get_random_bytes
|
||||
|
||||
raw_ofb_lib = load_pycryptodome_raw_lib("Cryptodome.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 = ["encrypt", "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 "encrypt" not in self._next:
|
||||
raise TypeError("encrypt() cannot be called after decrypt()")
|
||||
self._next = ["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 "decrypt" not in self._next:
|
||||
raise TypeError("decrypt() cannot be called after encrypt()")
|
||||
self._next = ["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 ``Cryptodome.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)
|
25
resources/lib/deps/Cryptodome/Cipher/_mode_ofb.pyi
Normal file
25
resources/lib/deps/Cryptodome/Cipher/_mode_ofb.pyi
Normal file
|
@ -0,0 +1,25 @@
|
|||
from typing import Union, overload
|
||||
|
||||
from Cryptodome.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: ...
|
||||
|
206
resources/lib/deps/Cryptodome/Cipher/_mode_openpgp.py
Normal file
206
resources/lib/deps/Cryptodome/Cipher/_mode_openpgp.py
Normal file
|
@ -0,0 +1,206 @@
|
|||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
"""
|
||||
OpenPGP mode.
|
||||
"""
|
||||
|
||||
__all__ = ['OpenPgpMode']
|
||||
|
||||
from Cryptodome.Util.py3compat import _copy_bytes
|
||||
from Cryptodome.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)
|
20
resources/lib/deps/Cryptodome/Cipher/_mode_openpgp.pyi
Normal file
20
resources/lib/deps/Cryptodome/Cipher/_mode_openpgp.pyi
Normal file
|
@ -0,0 +1,20 @@
|
|||
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: ...
|
||||
|
392
resources/lib/deps/Cryptodome/Cipher/_mode_siv.py
Normal file
392
resources/lib/deps/Cryptodome/Cipher/_mode_siv.py
Normal file
|
@ -0,0 +1,392 @@
|
|||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
"""
|
||||
Synthetic Initialization Vector (SIV) mode.
|
||||
"""
|
||||
|
||||
__all__ = ['SivMode']
|
||||
|
||||
from binascii import hexlify, unhexlify
|
||||
|
||||
from Cryptodome.Util.py3compat import bord, _copy_bytes
|
||||
|
||||
from Cryptodome.Util._raw_api import is_buffer
|
||||
|
||||
from Cryptodome.Util.number import long_to_bytes, bytes_to_long
|
||||
from Cryptodome.Protocol.KDF import _S2V
|
||||
from Cryptodome.Hash import BLAKE2s
|
||||
from Cryptodome.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 = ["update", "encrypt", "decrypt",
|
||||
"digest", "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 "update" not in self._next:
|
||||
raise TypeError("update() can only be called"
|
||||
" immediately after initialization")
|
||||
|
||||
self._next = ["update", "encrypt", "decrypt",
|
||||
"digest", "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 "digest" not in self._next:
|
||||
raise TypeError("digest() cannot be called when decrypting"
|
||||
" or validating a message")
|
||||
self._next = ["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 "verify" not in self._next:
|
||||
raise TypeError("verify() cannot be called"
|
||||
" when encrypting a message")
|
||||
self._next = ["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 "encrypt" not in self._next:
|
||||
raise TypeError("encrypt() can only be called after"
|
||||
" initialization or an update()")
|
||||
|
||||
self._next = ["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 "decrypt" not in self._next:
|
||||
raise TypeError("decrypt() can only be called"
|
||||
" after initialization or an update()")
|
||||
self._next = ["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 `Cryptodome.Cipher`
|
||||
(like `Cryptodome.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)
|
38
resources/lib/deps/Cryptodome/Cipher/_mode_siv.pyi
Normal file
38
resources/lib/deps/Cryptodome/Cipher/_mode_siv.pyi
Normal file
|
@ -0,0 +1,38 @@
|
|||
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: ...
|
BIN
resources/lib/deps/Cryptodome/Cipher/_pkcs1_decode.abi3.so
Executable file
BIN
resources/lib/deps/Cryptodome/Cipher/_pkcs1_decode.abi3.so
Executable file
Binary file not shown.
41
resources/lib/deps/Cryptodome/Cipher/_pkcs1_oaep_decode.py
Normal file
41
resources/lib/deps/Cryptodome/Cipher/_pkcs1_oaep_decode.py
Normal file
|
@ -0,0 +1,41 @@
|
|||
from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, c_size_t,
|
||||
c_uint8_ptr)
|
||||
|
||||
|
||||
_raw_pkcs1_decode = load_pycryptodome_raw_lib("Cryptodome.Cipher._pkcs1_decode",
|
||||
"""
|
||||
int pkcs1_decode(const uint8_t *em, size_t len_em,
|
||||
const uint8_t *sentinel, size_t len_sentinel,
|
||||
size_t expected_pt_len,
|
||||
uint8_t *output);
|
||||
|
||||
int oaep_decode(const uint8_t *em,
|
||||
size_t em_len,
|
||||
const uint8_t *lHash,
|
||||
size_t hLen,
|
||||
const uint8_t *db,
|
||||
size_t db_len);
|
||||
""")
|
||||
|
||||
|
||||
def pkcs1_decode(em, sentinel, expected_pt_len, output):
|
||||
if len(em) != len(output):
|
||||
raise ValueError("Incorrect output length")
|
||||
|
||||
ret = _raw_pkcs1_decode.pkcs1_decode(c_uint8_ptr(em),
|
||||
c_size_t(len(em)),
|
||||
c_uint8_ptr(sentinel),
|
||||
c_size_t(len(sentinel)),
|
||||
c_size_t(expected_pt_len),
|
||||
c_uint8_ptr(output))
|
||||
return ret
|
||||
|
||||
|
||||
def oaep_decode(em, lHash, db):
|
||||
ret = _raw_pkcs1_decode.oaep_decode(c_uint8_ptr(em),
|
||||
c_size_t(len(em)),
|
||||
c_uint8_ptr(lHash),
|
||||
c_size_t(len(lHash)),
|
||||
c_uint8_ptr(db),
|
||||
c_size_t(len(db)))
|
||||
return ret
|
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_aes.abi3.so
Executable file
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_aes.abi3.so
Executable file
Binary file not shown.
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_aesni.abi3.so
Executable file
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_aesni.abi3.so
Executable file
Binary file not shown.
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_arc2.abi3.so
Executable file
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_arc2.abi3.so
Executable file
Binary file not shown.
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_blowfish.abi3.so
Executable file
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_blowfish.abi3.so
Executable file
Binary file not shown.
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_cast.abi3.so
Executable file
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_cast.abi3.so
Executable file
Binary file not shown.
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_cbc.abi3.so
Executable file
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_cbc.abi3.so
Executable file
Binary file not shown.
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_cfb.abi3.so
Executable file
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_cfb.abi3.so
Executable file
Binary file not shown.
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_ctr.abi3.so
Executable file
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_ctr.abi3.so
Executable file
Binary file not shown.
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_des.abi3.so
Executable file
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_des.abi3.so
Executable file
Binary file not shown.
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_des3.abi3.so
Executable file
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_des3.abi3.so
Executable file
Binary file not shown.
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_ecb.abi3.so
Executable file
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_ecb.abi3.so
Executable file
Binary file not shown.
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_eksblowfish.abi3.so
Executable file
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_eksblowfish.abi3.so
Executable file
Binary file not shown.
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_ocb.abi3.so
Executable file
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_ocb.abi3.so
Executable file
Binary file not shown.
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_ofb.abi3.so
Executable file
BIN
resources/lib/deps/Cryptodome/Cipher/_raw_ofb.abi3.so
Executable file
Binary file not shown.
247
resources/lib/deps/Cryptodome/Hash/BLAKE2b.py
Normal file
247
resources/lib/deps/Cryptodome/Hash/BLAKE2b.py
Normal file
|
@ -0,0 +1,247 @@
|
|||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
from binascii import unhexlify
|
||||
|
||||
from Cryptodome.Util.py3compat import bord, tobytes
|
||||
|
||||
from Cryptodome.Random import get_random_bytes
|
||||
from Cryptodome.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("Cryptodome.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_bits' 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("BLAKE2b key cannot exceed 64 bytes")
|
||||
|
||||
if kwargs:
|
||||
raise TypeError("Unknown parameters: " + str(kwargs))
|
||||
|
||||
return BLAKE2b_Hash(data, key, digest_bytes, update_after_digest)
|
32
resources/lib/deps/Cryptodome/Hash/BLAKE2b.pyi
Normal file
32
resources/lib/deps/Cryptodome/Hash/BLAKE2b.pyi
Normal file
|
@ -0,0 +1,32 @@
|
|||
from typing import Any, Union
|
||||
from types import ModuleType
|
||||
|
||||
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: ...
|
247
resources/lib/deps/Cryptodome/Hash/BLAKE2s.py
Normal file
247
resources/lib/deps/Cryptodome/Hash/BLAKE2s.py
Normal file
|
@ -0,0 +1,247 @@
|
|||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
from binascii import unhexlify
|
||||
|
||||
from Cryptodome.Util.py3compat import bord, tobytes
|
||||
|
||||
from Cryptodome.Random import get_random_bytes
|
||||
from Cryptodome.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("Cryptodome.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_bits' 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)
|
26
resources/lib/deps/Cryptodome/Hash/BLAKE2s.pyi
Normal file
26
resources/lib/deps/Cryptodome/Hash/BLAKE2s.pyi
Normal file
|
@ -0,0 +1,26 @@
|
|||
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: ...
|
306
resources/lib/deps/Cryptodome/Hash/CMAC.py
Normal file
306
resources/lib/deps/Cryptodome/Hash/CMAC.py
Normal file
|
@ -0,0 +1,306 @@
|
|||
# -*- 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 Cryptodome.Hash import BLAKE2s
|
||||
from Cryptodome.Util.strxor import strxor
|
||||
from Cryptodome.Util.number import long_to_bytes, bytes_to_long
|
||||
from Cryptodome.Util.py3compat import bord, tobytes, _copy_bytes
|
||||
from Cryptodome.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):
|
||||
"""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=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:`Cryptodome.Cipher`.
|
||||
The cipher's block size has to be 128 bits,
|
||||
like :mod:`Cryptodome.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)
|
30
resources/lib/deps/Cryptodome/Hash/CMAC.pyi
Normal file
30
resources/lib/deps/Cryptodome/Hash/CMAC.pyi
Normal file
|
@ -0,0 +1,30 @@
|
|||
from types import ModuleType
|
||||
from typing import Union, Dict, Any
|
||||
|
||||
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[str, Any],
|
||||
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[str, Any] = ...,
|
||||
mac_len: int = ...,
|
||||
update_after_digest: bool = ...) -> CMAC: ...
|
238
resources/lib/deps/Cryptodome/Hash/HMAC.py
Normal file
238
resources/lib/deps/Cryptodome/Hash/HMAC.py
Normal file
|
@ -0,0 +1,238 @@
|
|||
#
|
||||
# HMAC.py - Implements the HMAC algorithm as described by RFC 2104.
|
||||
#
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
from Cryptodome.Util.py3compat import bord, tobytes
|
||||
|
||||
from binascii import unhexlify
|
||||
|
||||
from Cryptodome.Hash import BLAKE2s
|
||||
from Cryptodome.Util.strxor import strxor
|
||||
from Cryptodome.Random import get_random_bytes
|
||||
|
||||
__all__ = ['new', 'HMAC']
|
||||
|
||||
_hash2hmac_oid = {
|
||||
'1.3.14.3.2.26': '1.2.840.113549.2.7', # SHA-1
|
||||
'2.16.840.1.101.3.4.2.4': '1.2.840.113549.2.8', # SHA-224
|
||||
'2.16.840.1.101.3.4.2.1': '1.2.840.113549.2.9', # SHA-256
|
||||
'2.16.840.1.101.3.4.2.2': '1.2.840.113549.2.10', # SHA-384
|
||||
'2.16.840.1.101.3.4.2.3': '1.2.840.113549.2.11', # SHA-512
|
||||
'2.16.840.1.101.3.4.2.5': '1.2.840.113549.2.12', # SHA-512_224
|
||||
'2.16.840.1.101.3.4.2.6': '1.2.840.113549.2.13', # SHA-512_256
|
||||
'2.16.840.1.101.3.4.2.7': '2.16.840.1.101.3.4.2.13', # SHA-3 224
|
||||
'2.16.840.1.101.3.4.2.8': '2.16.840.1.101.3.4.2.14', # SHA-3 256
|
||||
'2.16.840.1.101.3.4.2.9': '2.16.840.1.101.3.4.2.15', # SHA-3 384
|
||||
'2.16.840.1.101.3.4.2.10': '2.16.840.1.101.3.4.2.16', # SHA-3 512
|
||||
}
|
||||
|
||||
_hmac2hash_oid = {v: k for k, v in _hash2hmac_oid.items()}
|
||||
|
||||
|
||||
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
|
||||
|
||||
:ivar oid: the ASN.1 object ID of the HMAC algorithm.
|
||||
Only present if the algorithm was officially assigned one.
|
||||
"""
|
||||
|
||||
def __init__(self, key, msg=b"", digestmod=None):
|
||||
|
||||
if digestmod is None:
|
||||
from Cryptodome.Hash import MD5
|
||||
digestmod = MD5
|
||||
|
||||
if msg is None:
|
||||
msg = b""
|
||||
|
||||
# Size of the MAC tag
|
||||
self.digest_size = digestmod.digest_size
|
||||
|
||||
self._digestmod = digestmod
|
||||
|
||||
# Hash OID --> HMAC OID
|
||||
try:
|
||||
self.oid = _hash2hmac_oid[digestmod.oid]
|
||||
except (KeyError, AttributeError):
|
||||
pass
|
||||
|
||||
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:`Cryptodome.Hash.MD5`.
|
||||
|
||||
Returns:
|
||||
An :class:`HMAC` object
|
||||
"""
|
||||
|
||||
return HMAC(key, msg, digestmod)
|
25
resources/lib/deps/Cryptodome/Hash/HMAC.pyi
Normal file
25
resources/lib/deps/Cryptodome/Hash/HMAC.pyi
Normal file
|
@ -0,0 +1,25 @@
|
|||
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: ...
|
179
resources/lib/deps/Cryptodome/Hash/KMAC128.py
Normal file
179
resources/lib/deps/Cryptodome/Hash/KMAC128.py
Normal file
|
@ -0,0 +1,179 @@
|
|||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2021, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
from binascii import unhexlify
|
||||
|
||||
from Cryptodome.Util.py3compat import bord, tobytes, is_bytes
|
||||
from Cryptodome.Random import get_random_bytes
|
||||
|
||||
from . import cSHAKE128, SHA3_256
|
||||
from .cSHAKE128 import _bytepad, _encode_str, _right_encode
|
||||
|
||||
|
||||
class KMAC_Hash(object):
|
||||
"""A KMAC hash object.
|
||||
Do not instantiate directly.
|
||||
Use the :func:`new` function.
|
||||
"""
|
||||
|
||||
def __init__(self, data, key, mac_len, custom,
|
||||
oid_variant, cshake, rate):
|
||||
|
||||
# See https://tools.ietf.org/html/rfc8702
|
||||
self.oid = "2.16.840.1.101.3.4.2." + oid_variant
|
||||
self.digest_size = mac_len
|
||||
|
||||
self._mac = None
|
||||
|
||||
partial_newX = _bytepad(_encode_str(tobytes(key)), rate)
|
||||
self._cshake = cshake._new(partial_newX, custom, b"KMAC")
|
||||
|
||||
if data:
|
||||
self._cshake.update(data)
|
||||
|
||||
def update(self, data):
|
||||
"""Authenticate the next chunk of message.
|
||||
|
||||
Args:
|
||||
data (bytes/bytearray/memoryview): The next chunk of the message to
|
||||
authenticate.
|
||||
"""
|
||||
|
||||
if self._mac:
|
||||
raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
|
||||
|
||||
self._cshake.update(data)
|
||||
return self
|
||||
|
||||
def digest(self):
|
||||
"""Return the **binary** (non-printable) MAC tag of the message.
|
||||
|
||||
:return: The MAC tag. Binary form.
|
||||
:rtype: byte string
|
||||
"""
|
||||
|
||||
if not self._mac:
|
||||
self._cshake.update(_right_encode(self.digest_size * 8))
|
||||
self._mac = self._cshake.read(self.digest_size)
|
||||
|
||||
return self._mac
|
||||
|
||||
def hexdigest(self):
|
||||
"""Return the **printable** MAC tag of the message.
|
||||
|
||||
:return: The MAC tag. 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 = SHA3_256.new(secret + mac_tag)
|
||||
mac2 = SHA3_256.new(secret + 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 KMAC hash object.
|
||||
See :func:`new`.
|
||||
"""
|
||||
|
||||
if "mac_len" not in kwargs:
|
||||
kwargs["mac_len"] = self.digest_size
|
||||
|
||||
return new(**kwargs)
|
||||
|
||||
|
||||
def new(**kwargs):
|
||||
"""Create a new KMAC128 object.
|
||||
|
||||
Args:
|
||||
key (bytes/bytearray/memoryview):
|
||||
The key to use to compute the MAC.
|
||||
It must be at least 128 bits long (16 bytes).
|
||||
data (bytes/bytearray/memoryview):
|
||||
Optional. The very first chunk of the message to authenticate.
|
||||
It is equivalent to an early call to :meth:`KMAC_Hash.update`.
|
||||
mac_len (integer):
|
||||
Optional. The size of the authentication tag, in bytes.
|
||||
Default is 64. Minimum is 8.
|
||||
custom (bytes/bytearray/memoryview):
|
||||
Optional. A customization byte string (``S`` in SP 800-185).
|
||||
|
||||
Returns:
|
||||
A :class:`KMAC_Hash` hash object
|
||||
"""
|
||||
|
||||
key = kwargs.pop("key", None)
|
||||
if not is_bytes(key):
|
||||
raise TypeError("You must pass a key to KMAC128")
|
||||
if len(key) < 16:
|
||||
raise ValueError("The key must be at least 128 bits long (16 bytes)")
|
||||
|
||||
data = kwargs.pop("data", None)
|
||||
|
||||
mac_len = kwargs.pop("mac_len", 64)
|
||||
if mac_len < 8:
|
||||
raise ValueError("'mac_len' must be 8 bytes or more")
|
||||
|
||||
custom = kwargs.pop("custom", b"")
|
||||
|
||||
if kwargs:
|
||||
raise TypeError("Unknown parameters: " + str(kwargs))
|
||||
|
||||
return KMAC_Hash(data, key, mac_len, custom, "19", cSHAKE128, 168)
|
33
resources/lib/deps/Cryptodome/Hash/KMAC128.pyi
Normal file
33
resources/lib/deps/Cryptodome/Hash/KMAC128.pyi
Normal file
|
@ -0,0 +1,33 @@
|
|||
from typing import Union
|
||||
from types import ModuleType
|
||||
|
||||
Buffer = Union[bytes, bytearray, memoryview]
|
||||
|
||||
class KMAC_Hash(object):
|
||||
|
||||
def __init__(self,
|
||||
data: Buffer,
|
||||
key: Buffer,
|
||||
mac_len: int,
|
||||
custom: Buffer,
|
||||
oid_variant: str,
|
||||
cshake: ModuleType,
|
||||
rate: int) -> None: ...
|
||||
|
||||
def update(self, data: Buffer) -> KMAC_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 = ...,
|
||||
mac_len: int = ...,
|
||||
key: Buffer = ...,
|
||||
custom: Buffer = ...) -> KMAC_Hash: ...
|
||||
|
||||
|
||||
def new(key: Buffer,
|
||||
data: Buffer = ...,
|
||||
mac_len: int = ...,
|
||||
custom: Buffer = ...) -> KMAC_Hash: ...
|
74
resources/lib/deps/Cryptodome/Hash/KMAC256.py
Normal file
74
resources/lib/deps/Cryptodome/Hash/KMAC256.py
Normal file
|
@ -0,0 +1,74 @@
|
|||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2021, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
from Cryptodome.Util.py3compat import is_bytes
|
||||
|
||||
from .KMAC128 import KMAC_Hash
|
||||
from . import cSHAKE256
|
||||
|
||||
|
||||
def new(**kwargs):
|
||||
"""Create a new KMAC256 object.
|
||||
|
||||
Args:
|
||||
key (bytes/bytearray/memoryview):
|
||||
The key to use to compute the MAC.
|
||||
It must be at least 256 bits long (32 bytes).
|
||||
data (bytes/bytearray/memoryview):
|
||||
Optional. The very first chunk of the message to authenticate.
|
||||
It is equivalent to an early call to :meth:`KMAC_Hash.update`.
|
||||
mac_len (integer):
|
||||
Optional. The size of the authentication tag, in bytes.
|
||||
Default is 64. Minimum is 8.
|
||||
custom (bytes/bytearray/memoryview):
|
||||
Optional. A customization byte string (``S`` in SP 800-185).
|
||||
|
||||
Returns:
|
||||
A :class:`KMAC_Hash` hash object
|
||||
"""
|
||||
|
||||
key = kwargs.pop("key", None)
|
||||
if not is_bytes(key):
|
||||
raise TypeError("You must pass a key to KMAC256")
|
||||
if len(key) < 32:
|
||||
raise ValueError("The key must be at least 256 bits long (32 bytes)")
|
||||
|
||||
data = kwargs.pop("data", None)
|
||||
|
||||
mac_len = kwargs.pop("mac_len", 64)
|
||||
if mac_len < 8:
|
||||
raise ValueError("'mac_len' must be 8 bytes or more")
|
||||
|
||||
custom = kwargs.pop("custom", b"")
|
||||
|
||||
if kwargs:
|
||||
raise TypeError("Unknown parameters: " + str(kwargs))
|
||||
|
||||
return KMAC_Hash(data, key, mac_len, custom, "20", cSHAKE256, 136)
|
10
resources/lib/deps/Cryptodome/Hash/KMAC256.pyi
Normal file
10
resources/lib/deps/Cryptodome/Hash/KMAC256.pyi
Normal file
|
@ -0,0 +1,10 @@
|
|||
from typing import Union
|
||||
|
||||
from .KMAC128 import KMAC_Hash
|
||||
|
||||
Buffer = Union[bytes, bytearray, memoryview]
|
||||
|
||||
def new(key: Buffer,
|
||||
data: Buffer = ...,
|
||||
mac_len: int = ...,
|
||||
custom: Buffer = ...) -> KMAC_Hash: ...
|
222
resources/lib/deps/Cryptodome/Hash/KangarooTwelve.py
Normal file
222
resources/lib/deps/Cryptodome/Hash/KangarooTwelve.py
Normal file
|
@ -0,0 +1,222 @@
|
|||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2021, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
from Cryptodome.Util.number import long_to_bytes
|
||||
from Cryptodome.Util.py3compat import bchr
|
||||
|
||||
from . import TurboSHAKE128
|
||||
|
||||
def _length_encode(x):
|
||||
if x == 0:
|
||||
return b'\x00'
|
||||
|
||||
S = long_to_bytes(x)
|
||||
return S + bchr(len(S))
|
||||
|
||||
|
||||
# Possible states for a KangarooTwelve instance, which depend on the amount of data processed so far.
|
||||
SHORT_MSG = 1 # Still within the first 8192 bytes, but it is not certain we will exceed them.
|
||||
LONG_MSG_S0 = 2 # Still within the first 8192 bytes, and it is certain we will exceed them.
|
||||
LONG_MSG_SX = 3 # Beyond the first 8192 bytes.
|
||||
SQUEEZING = 4 # No more data to process.
|
||||
|
||||
|
||||
class K12_XOF(object):
|
||||
"""A KangarooTwelve hash object.
|
||||
Do not instantiate directly.
|
||||
Use the :func:`new` function.
|
||||
"""
|
||||
|
||||
def __init__(self, data, custom):
|
||||
|
||||
if custom == None:
|
||||
custom = b''
|
||||
|
||||
self._custom = custom + _length_encode(len(custom))
|
||||
self._state = SHORT_MSG
|
||||
self._padding = None # Final padding is only decided in read()
|
||||
|
||||
# Internal hash that consumes FinalNode
|
||||
# The real domain separation byte will be known before squeezing
|
||||
self._hash1 = TurboSHAKE128.new(domain=1)
|
||||
self._length1 = 0
|
||||
|
||||
# Internal hash that produces CV_i (reset each time)
|
||||
self._hash2 = None
|
||||
self._length2 = 0
|
||||
|
||||
# Incremented by one for each 8192-byte block
|
||||
self._ctr = 0
|
||||
|
||||
if data:
|
||||
self.update(data)
|
||||
|
||||
def update(self, data):
|
||||
"""Hash the next piece of data.
|
||||
|
||||
.. note::
|
||||
For better performance, submit chunks with a length multiple of 8192 bytes.
|
||||
|
||||
Args:
|
||||
data (byte string/byte array/memoryview): The next chunk of the
|
||||
message to hash.
|
||||
"""
|
||||
|
||||
if self._state == SQUEEZING:
|
||||
raise TypeError("You cannot call 'update' after the first 'read'")
|
||||
|
||||
if self._state == SHORT_MSG:
|
||||
next_length = self._length1 + len(data)
|
||||
|
||||
if next_length + len(self._custom) <= 8192:
|
||||
self._length1 = next_length
|
||||
self._hash1.update(data)
|
||||
return self
|
||||
|
||||
# Switch to tree hashing
|
||||
self._state = LONG_MSG_S0
|
||||
|
||||
if self._state == LONG_MSG_S0:
|
||||
data_mem = memoryview(data)
|
||||
assert(self._length1 < 8192)
|
||||
dtc = min(len(data), 8192 - self._length1)
|
||||
self._hash1.update(data_mem[:dtc])
|
||||
self._length1 += dtc
|
||||
|
||||
if self._length1 < 8192:
|
||||
return self
|
||||
|
||||
# Finish hashing S_0 and start S_1
|
||||
assert(self._length1 == 8192)
|
||||
|
||||
divider = b'\x03' + b'\x00' * 7
|
||||
self._hash1.update(divider)
|
||||
self._length1 += 8
|
||||
|
||||
self._hash2 = TurboSHAKE128.new(domain=0x0B)
|
||||
self._length2 = 0
|
||||
self._ctr = 1
|
||||
|
||||
self._state = LONG_MSG_SX
|
||||
return self.update(data_mem[dtc:])
|
||||
|
||||
# LONG_MSG_SX
|
||||
assert(self._state == LONG_MSG_SX)
|
||||
index = 0
|
||||
len_data = len(data)
|
||||
|
||||
# All iteractions could actually run in parallel
|
||||
data_mem = memoryview(data)
|
||||
while index < len_data:
|
||||
|
||||
new_index = min(index + 8192 - self._length2, len_data)
|
||||
self._hash2.update(data_mem[index:new_index])
|
||||
self._length2 += new_index - index
|
||||
index = new_index
|
||||
|
||||
if self._length2 == 8192:
|
||||
cv_i = self._hash2.read(32)
|
||||
self._hash1.update(cv_i)
|
||||
self._length1 += 32
|
||||
self._hash2._reset()
|
||||
self._length2 = 0
|
||||
self._ctr += 1
|
||||
|
||||
return self
|
||||
|
||||
def read(self, length):
|
||||
"""
|
||||
Produce more bytes of the digest.
|
||||
|
||||
.. 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
|
||||
"""
|
||||
|
||||
custom_was_consumed = False
|
||||
|
||||
if self._state == SHORT_MSG:
|
||||
self._hash1.update(self._custom)
|
||||
self._padding = 0x07
|
||||
self._state = SQUEEZING
|
||||
|
||||
if self._state == LONG_MSG_S0:
|
||||
self.update(self._custom)
|
||||
custom_was_consumed = True
|
||||
assert(self._state == LONG_MSG_SX)
|
||||
|
||||
if self._state == LONG_MSG_SX:
|
||||
if not custom_was_consumed:
|
||||
self.update(self._custom)
|
||||
|
||||
# Is there still some leftover data in hash2?
|
||||
if self._length2 > 0:
|
||||
cv_i = self._hash2.read(32)
|
||||
self._hash1.update(cv_i)
|
||||
self._length1 += 32
|
||||
self._hash2._reset()
|
||||
self._length2 = 0
|
||||
self._ctr += 1
|
||||
|
||||
trailer = _length_encode(self._ctr - 1) + b'\xFF\xFF'
|
||||
self._hash1.update(trailer)
|
||||
|
||||
self._padding = 0x06
|
||||
self._state = SQUEEZING
|
||||
|
||||
self._hash1._domain = self._padding
|
||||
return self._hash1.read(length)
|
||||
|
||||
def new(self, data=None, custom=b''):
|
||||
return type(self)(data, custom)
|
||||
|
||||
|
||||
def new(data=None, custom=None):
|
||||
"""Return a fresh instance of a KangarooTwelve 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:`update`.
|
||||
custom (bytes):
|
||||
Optional.
|
||||
A customization byte string.
|
||||
|
||||
:Return: A :class:`K12_XOF` object
|
||||
"""
|
||||
|
||||
return K12_XOF(data, custom)
|
16
resources/lib/deps/Cryptodome/Hash/KangarooTwelve.pyi
Normal file
16
resources/lib/deps/Cryptodome/Hash/KangarooTwelve.pyi
Normal file
|
@ -0,0 +1,16 @@
|
|||
from typing import Union, Optional
|
||||
|
||||
Buffer = Union[bytes, bytearray, memoryview]
|
||||
|
||||
class K12_XOF(object):
|
||||
def __init__(self,
|
||||
data: Optional[Buffer] = ...,
|
||||
custom: Optional[bytes] = ...) -> None: ...
|
||||
def update(self, data: Buffer) -> K12_XOF: ...
|
||||
def read(self, length: int) -> bytes: ...
|
||||
def new(self,
|
||||
data: Optional[Buffer] = ...,
|
||||
custom: Optional[bytes] = ...) -> None: ...
|
||||
|
||||
def new(data: Optional[Buffer] = ...,
|
||||
custom: Optional[Buffer] = ...) -> K12_XOF: ...
|
166
resources/lib/deps/Cryptodome/Hash/MD2.py
Normal file
166
resources/lib/deps/Cryptodome/Hash/MD2.py
Normal file
|
@ -0,0 +1,166 @@
|
|||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
from Cryptodome.Util.py3compat import bord
|
||||
|
||||
from Cryptodome.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(
|
||||
"Cryptodome.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
|
19
resources/lib/deps/Cryptodome/Hash/MD2.pyi
Normal file
19
resources/lib/deps/Cryptodome/Hash/MD2.pyi
Normal file
|
@ -0,0 +1,19 @@
|
|||
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
|
185
resources/lib/deps/Cryptodome/Hash/MD4.py
Normal file
185
resources/lib/deps/Cryptodome/Hash/MD4.py
Normal file
|
@ -0,0 +1,185 @@
|
|||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
"""
|
||||
MD4 is specified in RFC1320_ and produces the 128 bit digest of a message.
|
||||
|
||||
>>> from Cryptodome.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 Cryptodome.Util.py3compat import bord
|
||||
|
||||
from Cryptodome.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(
|
||||
"Cryptodome.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
|
19
resources/lib/deps/Cryptodome/Hash/MD4.pyi
Normal file
19
resources/lib/deps/Cryptodome/Hash/MD4.pyi
Normal file
|
@ -0,0 +1,19 @@
|
|||
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
|
184
resources/lib/deps/Cryptodome/Hash/MD5.py
Normal file
184
resources/lib/deps/Cryptodome/Hash/MD5.py
Normal file
|
@ -0,0 +1,184 @@
|
|||
# -*- 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 Cryptodome.Util.py3compat import *
|
||||
|
||||
from Cryptodome.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("Cryptodome.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)
|
19
resources/lib/deps/Cryptodome/Hash/MD5.pyi
Normal file
19
resources/lib/deps/Cryptodome/Hash/MD5.pyi
Normal file
|
@ -0,0 +1,19 @@
|
|||
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
|
217
resources/lib/deps/Cryptodome/Hash/Poly1305.py
Normal file
217
resources/lib/deps/Cryptodome/Hash/Poly1305.py
Normal file
|
@ -0,0 +1,217 @@
|
|||
# -*- 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 Cryptodome.Util.py3compat import bord, tobytes, _copy_bytes
|
||||
|
||||
from Cryptodome.Hash import BLAKE2s
|
||||
from Cryptodome.Random import get_random_bytes
|
||||
from Cryptodome.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("Cryptodome.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 ``Cryptodome.Cipher``):
|
||||
The cipher algorithm to use for deriving the Poly1305
|
||||
key pair *(r, s)*.
|
||||
It can only be ``Cryptodome.Cipher.AES`` or ``Cryptodome.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
|
24
resources/lib/deps/Cryptodome/Hash/Poly1305.pyi
Normal file
24
resources/lib/deps/Cryptodome/Hash/Poly1305.pyi
Normal file
|
@ -0,0 +1,24 @@
|
|||
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: ...
|
26
resources/lib/deps/Cryptodome/Hash/RIPEMD.py
Normal file
26
resources/lib/deps/Cryptodome/Hash/RIPEMD.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
# -*- 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
|
||||
# Cryptodome.Hash.RIPEMD
|
||||
|
||||
"""Deprecated alias for `Cryptodome.Hash.RIPEMD160`"""
|
||||
|
||||
from Cryptodome.Hash.RIPEMD160 import new, block_size, digest_size
|
3
resources/lib/deps/Cryptodome/Hash/RIPEMD.pyi
Normal file
3
resources/lib/deps/Cryptodome/Hash/RIPEMD.pyi
Normal file
|
@ -0,0 +1,3 @@
|
|||
# This file exists for backward compatibility with old code that refers to
|
||||
# Cryptodome.Hash.SHA
|
||||
|
169
resources/lib/deps/Cryptodome/Hash/RIPEMD160.py
Normal file
169
resources/lib/deps/Cryptodome/Hash/RIPEMD160.py
Normal file
|
@ -0,0 +1,169 @@
|
|||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
from Cryptodome.Util.py3compat import bord
|
||||
|
||||
from Cryptodome.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(
|
||||
"Cryptodome.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
|
19
resources/lib/deps/Cryptodome/Hash/RIPEMD160.pyi
Normal file
19
resources/lib/deps/Cryptodome/Hash/RIPEMD160.pyi
Normal file
|
@ -0,0 +1,19 @@
|
|||
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
|
24
resources/lib/deps/Cryptodome/Hash/SHA.py
Normal file
24
resources/lib/deps/Cryptodome/Hash/SHA.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
# -*- 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
|
||||
# Cryptodome.Hash.SHA
|
||||
|
||||
from Cryptodome.Hash.SHA1 import __doc__, new, block_size, digest_size
|
4
resources/lib/deps/Cryptodome/Hash/SHA.pyi
Normal file
4
resources/lib/deps/Cryptodome/Hash/SHA.pyi
Normal file
|
@ -0,0 +1,4 @@
|
|||
# This file exists for backward compatibility with old code that refers to
|
||||
# Cryptodome.Hash.SHA
|
||||
|
||||
from Cryptodome.Hash.SHA1 import __doc__, new, block_size, digest_size
|
185
resources/lib/deps/Cryptodome/Hash/SHA1.py
Normal file
185
resources/lib/deps/Cryptodome/Hash/SHA1.py
Normal file
|
@ -0,0 +1,185 @@
|
|||
# -*- 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 Cryptodome.Util.py3compat import *
|
||||
|
||||
from Cryptodome.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("Cryptodome.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)
|
19
resources/lib/deps/Cryptodome/Hash/SHA1.pyi
Normal file
19
resources/lib/deps/Cryptodome/Hash/SHA1.pyi
Normal file
|
@ -0,0 +1,19 @@
|
|||
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
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue