aboutsummaryrefslogtreecommitdiff
path: root/frozen_deps/Cryptodome
diff options
context:
space:
mode:
authorDeterminant <[email protected]>2020-11-17 20:04:09 -0500
committerDeterminant <[email protected]>2020-11-17 20:04:09 -0500
commitc4d90bf4ea0c5b7a016028ed994de19638d3113b (patch)
tree693279a91311155f565e90ecd2d93bf701d6d4e9 /frozen_deps/Cryptodome
parent3bef51eec2299403467e621ae660cef3f9256ac8 (diff)
support saving as a keystore file
Diffstat (limited to 'frozen_deps/Cryptodome')
-rw-r--r--frozen_deps/Cryptodome/Cipher/AES.py250
-rw-r--r--frozen_deps/Cryptodome/Cipher/AES.pyi47
-rw-r--r--frozen_deps/Cryptodome/Cipher/ARC2.py175
-rw-r--r--frozen_deps/Cryptodome/Cipher/ARC2.pyi35
-rw-r--r--frozen_deps/Cryptodome/Cipher/ARC4.py137
-rw-r--r--frozen_deps/Cryptodome/Cipher/ARC4.pyi16
-rw-r--r--frozen_deps/Cryptodome/Cipher/Blowfish.py159
-rw-r--r--frozen_deps/Cryptodome/Cipher/Blowfish.pyi35
-rw-r--r--frozen_deps/Cryptodome/Cipher/CAST.py159
-rw-r--r--frozen_deps/Cryptodome/Cipher/CAST.pyi35
-rw-r--r--frozen_deps/Cryptodome/Cipher/ChaCha20.py286
-rw-r--r--frozen_deps/Cryptodome/Cipher/ChaCha20.pyi25
-rw-r--r--frozen_deps/Cryptodome/Cipher/ChaCha20_Poly1305.py336
-rw-r--r--frozen_deps/Cryptodome/Cipher/ChaCha20_Poly1305.pyi28
-rw-r--r--frozen_deps/Cryptodome/Cipher/DES.py158
-rw-r--r--frozen_deps/Cryptodome/Cipher/DES.pyi35
-rw-r--r--frozen_deps/Cryptodome/Cipher/DES3.py187
-rw-r--r--frozen_deps/Cryptodome/Cipher/DES3.pyi37
-rw-r--r--frozen_deps/Cryptodome/Cipher/PKCS1_OAEP.py239
-rw-r--r--frozen_deps/Cryptodome/Cipher/PKCS1_OAEP.pyi35
-rw-r--r--frozen_deps/Cryptodome/Cipher/PKCS1_v1_5.py199
-rw-r--r--frozen_deps/Cryptodome/Cipher/PKCS1_v1_5.pyi17
-rw-r--r--frozen_deps/Cryptodome/Cipher/Salsa20.py167
-rw-r--r--frozen_deps/Cryptodome/Cipher/Salsa20.pyi27
-rwxr-xr-xfrozen_deps/Cryptodome/Cipher/_ARC4.cpython-38-x86_64-linux-gnu.sobin0 -> 14354 bytes
-rw-r--r--frozen_deps/Cryptodome/Cipher/_EKSBlowfish.py131
-rw-r--r--frozen_deps/Cryptodome/Cipher/_EKSBlowfish.pyi15
-rwxr-xr-xfrozen_deps/Cryptodome/Cipher/_Salsa20.cpython-38-x86_64-linux-gnu.sobin0 -> 21734 bytes
-rw-r--r--frozen_deps/Cryptodome/Cipher/__init__.py79
-rw-r--r--frozen_deps/Cryptodome/Cipher/__init__.pyi0
-rwxr-xr-xfrozen_deps/Cryptodome/Cipher/_chacha20.cpython-38-x86_64-linux-gnu.sobin0 -> 25741 bytes
-rw-r--r--frozen_deps/Cryptodome/Cipher/_mode_cbc.py293
-rw-r--r--frozen_deps/Cryptodome/Cipher/_mode_cbc.pyi25
-rw-r--r--frozen_deps/Cryptodome/Cipher/_mode_ccm.py650
-rw-r--r--frozen_deps/Cryptodome/Cipher/_mode_ccm.pyi47
-rw-r--r--frozen_deps/Cryptodome/Cipher/_mode_cfb.py293
-rw-r--r--frozen_deps/Cryptodome/Cipher/_mode_cfb.pyi26
-rw-r--r--frozen_deps/Cryptodome/Cipher/_mode_ctr.py393
-rw-r--r--frozen_deps/Cryptodome/Cipher/_mode_ctr.pyi27
-rw-r--r--frozen_deps/Cryptodome/Cipher/_mode_eax.py408
-rw-r--r--frozen_deps/Cryptodome/Cipher/_mode_eax.pyi45
-rw-r--r--frozen_deps/Cryptodome/Cipher/_mode_ecb.py218
-rw-r--r--frozen_deps/Cryptodome/Cipher/_mode_ecb.pyi19
-rw-r--r--frozen_deps/Cryptodome/Cipher/_mode_gcm.py620
-rw-r--r--frozen_deps/Cryptodome/Cipher/_mode_gcm.pyi45
-rw-r--r--frozen_deps/Cryptodome/Cipher/_mode_ocb.py525
-rw-r--r--frozen_deps/Cryptodome/Cipher/_mode_ocb.pyi36
-rw-r--r--frozen_deps/Cryptodome/Cipher/_mode_ofb.py282
-rw-r--r--frozen_deps/Cryptodome/Cipher/_mode_ofb.pyi25
-rw-r--r--frozen_deps/Cryptodome/Cipher/_mode_openpgp.py206
-rw-r--r--frozen_deps/Cryptodome/Cipher/_mode_openpgp.pyi20
-rw-r--r--frozen_deps/Cryptodome/Cipher/_mode_siv.py392
-rw-r--r--frozen_deps/Cryptodome/Cipher/_mode_siv.pyi38
-rwxr-xr-xfrozen_deps/Cryptodome/Cipher/_raw_aes.cpython-38-x86_64-linux-gnu.sobin0 -> 54112 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Cipher/_raw_aesni.cpython-38-x86_64-linux-gnu.sobin0 -> 52331 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Cipher/_raw_arc2.cpython-38-x86_64-linux-gnu.sobin0 -> 18917 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Cipher/_raw_blowfish.cpython-38-x86_64-linux-gnu.sobin0 -> 26938 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Cipher/_raw_cast.cpython-38-x86_64-linux-gnu.sobin0 -> 44422 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Cipher/_raw_cbc.cpython-38-x86_64-linux-gnu.sobin0 -> 17215 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Cipher/_raw_cfb.cpython-38-x86_64-linux-gnu.sobin0 -> 22696 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Cipher/_raw_ctr.cpython-38-x86_64-linux-gnu.sobin0 -> 23249 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Cipher/_raw_des.cpython-38-x86_64-linux-gnu.sobin0 -> 62525 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Cipher/_raw_des3.cpython-38-x86_64-linux-gnu.sobin0 -> 63370 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Cipher/_raw_ecb.cpython-38-x86_64-linux-gnu.sobin0 -> 10893 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Cipher/_raw_eksblowfish.cpython-38-x86_64-linux-gnu.sobin0 -> 58926 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Cipher/_raw_ocb.cpython-38-x86_64-linux-gnu.sobin0 -> 30281 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Cipher/_raw_ofb.cpython-38-x86_64-linux-gnu.sobin0 -> 14743 bytes
-rw-r--r--frozen_deps/Cryptodome/Hash/BLAKE2b.py247
-rw-r--r--frozen_deps/Cryptodome/Hash/BLAKE2b.pyi31
-rw-r--r--frozen_deps/Cryptodome/Hash/BLAKE2s.py247
-rw-r--r--frozen_deps/Cryptodome/Hash/BLAKE2s.pyi26
-rw-r--r--frozen_deps/Cryptodome/Hash/CMAC.py305
-rw-r--r--frozen_deps/Cryptodome/Hash/CMAC.pyi30
-rw-r--r--frozen_deps/Cryptodome/Hash/HMAC.py213
-rw-r--r--frozen_deps/Cryptodome/Hash/HMAC.pyi25
-rw-r--r--frozen_deps/Cryptodome/Hash/MD2.py166
-rw-r--r--frozen_deps/Cryptodome/Hash/MD2.pyi19
-rw-r--r--frozen_deps/Cryptodome/Hash/MD4.py185
-rw-r--r--frozen_deps/Cryptodome/Hash/MD4.pyi19
-rw-r--r--frozen_deps/Cryptodome/Hash/MD5.py184
-rw-r--r--frozen_deps/Cryptodome/Hash/MD5.pyi19
-rw-r--r--frozen_deps/Cryptodome/Hash/Poly1305.py217
-rw-r--r--frozen_deps/Cryptodome/Hash/Poly1305.pyi24
-rw-r--r--frozen_deps/Cryptodome/Hash/RIPEMD.py26
-rw-r--r--frozen_deps/Cryptodome/Hash/RIPEMD.pyi3
-rw-r--r--frozen_deps/Cryptodome/Hash/RIPEMD160.py169
-rw-r--r--frozen_deps/Cryptodome/Hash/RIPEMD160.pyi19
-rw-r--r--frozen_deps/Cryptodome/Hash/SHA.py24
-rw-r--r--frozen_deps/Cryptodome/Hash/SHA.pyi4
-rw-r--r--frozen_deps/Cryptodome/Hash/SHA1.py185
-rw-r--r--frozen_deps/Cryptodome/Hash/SHA1.pyi19
-rw-r--r--frozen_deps/Cryptodome/Hash/SHA224.py186
-rw-r--r--frozen_deps/Cryptodome/Hash/SHA224.pyi19
-rw-r--r--frozen_deps/Cryptodome/Hash/SHA256.py185
-rw-r--r--frozen_deps/Cryptodome/Hash/SHA256.pyi18
-rw-r--r--frozen_deps/Cryptodome/Hash/SHA384.py186
-rw-r--r--frozen_deps/Cryptodome/Hash/SHA384.pyi19
-rw-r--r--frozen_deps/Cryptodome/Hash/SHA3_224.py147
-rw-r--r--frozen_deps/Cryptodome/Hash/SHA3_224.pyi16
-rw-r--r--frozen_deps/Cryptodome/Hash/SHA3_256.py147
-rw-r--r--frozen_deps/Cryptodome/Hash/SHA3_256.pyi16
-rw-r--r--frozen_deps/Cryptodome/Hash/SHA3_384.py147
-rw-r--r--frozen_deps/Cryptodome/Hash/SHA3_384.pyi16
-rw-r--r--frozen_deps/Cryptodome/Hash/SHA3_512.py148
-rw-r--r--frozen_deps/Cryptodome/Hash/SHA3_512.pyi16
-rw-r--r--frozen_deps/Cryptodome/Hash/SHA512.py204
-rw-r--r--frozen_deps/Cryptodome/Hash/SHA512.pyi22
-rw-r--r--frozen_deps/Cryptodome/Hash/SHAKE128.py127
-rw-r--r--frozen_deps/Cryptodome/Hash/SHAKE128.pyi13
-rw-r--r--frozen_deps/Cryptodome/Hash/SHAKE256.py127
-rw-r--r--frozen_deps/Cryptodome/Hash/SHAKE256.pyi13
-rwxr-xr-xfrozen_deps/Cryptodome/Hash/_BLAKE2b.cpython-38-x86_64-linux-gnu.sobin0 -> 20015 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Hash/_BLAKE2s.cpython-38-x86_64-linux-gnu.sobin0 -> 20807 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Hash/_MD2.cpython-38-x86_64-linux-gnu.sobin0 -> 16919 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Hash/_MD4.cpython-38-x86_64-linux-gnu.sobin0 -> 19072 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Hash/_MD5.cpython-38-x86_64-linux-gnu.sobin0 -> 25434 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Hash/_RIPEMD160.cpython-38-x86_64-linux-gnu.sobin0 -> 27226 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Hash/_SHA1.cpython-38-x86_64-linux-gnu.sobin0 -> 84273 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Hash/_SHA224.cpython-38-x86_64-linux-gnu.sobin0 -> 35822 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Hash/_SHA256.cpython-38-x86_64-linux-gnu.sobin0 -> 35806 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Hash/_SHA384.cpython-38-x86_64-linux-gnu.sobin0 -> 41869 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Hash/_SHA512.cpython-38-x86_64-linux-gnu.sobin0 -> 41967 bytes
-rw-r--r--frozen_deps/Cryptodome/Hash/__init__.py22
-rw-r--r--frozen_deps/Cryptodome/Hash/__init__.pyi0
-rwxr-xr-xfrozen_deps/Cryptodome/Hash/_ghash_clmul.cpython-38-x86_64-linux-gnu.sobin0 -> 34203 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Hash/_ghash_portable.cpython-38-x86_64-linux-gnu.sobin0 -> 18711 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Hash/_keccak.cpython-38-x86_64-linux-gnu.sobin0 -> 26749 bytes
-rwxr-xr-xfrozen_deps/Cryptodome/Hash/_poly1305.cpython-38-x86_64-linux-gnu.sobin0 -> 25921 bytes
-rw-r--r--frozen_deps/Cryptodome/Hash/keccak.py173
-rw-r--r--frozen_deps/Cryptodome/Hash/keccak.pyi23
-rw-r--r--frozen_deps/Cryptodome/IO/PEM.py189
-rw-r--r--frozen_deps/Cryptodome/IO/PEM.pyi10
-rw-r--r--frozen_deps/Cryptodome/IO/PKCS8.py231
-rw-r--r--frozen_deps/Cryptodome/IO/PKCS8.pyi14
-rw-r--r--frozen_deps/Cryptodome/IO/_PBES.py435
-rw-r--r--frozen_deps/Cryptodome/IO/_PBES.pyi19
-rw-r--r--frozen_deps/Cryptodome/IO/__init__.py31
-rw-r--r--frozen_deps/Cryptodome/Math/Numbers.py42
-rw-r--r--frozen_deps/Cryptodome/Math/Numbers.pyi4
-rw-r--r--frozen_deps/Cryptodome/Math/Primality.py368
-rw-r--r--frozen_deps/Cryptodome/Math/Primality.pyi18
-rw-r--r--frozen_deps/Cryptodome/Math/_IntegerBase.py392
-rw-r--r--frozen_deps/Cryptodome/Math/_IntegerBase.pyi61
-rw-r--r--frozen_deps/Cryptodome/Math/_IntegerCustom.py111
-rw-r--r--frozen_deps/Cryptodome/Math/_IntegerCustom.pyi8
-rw-r--r--frozen_deps/Cryptodome/Math/_IntegerGMP.py708
-rw-r--r--frozen_deps/Cryptodome/Math/_IntegerGMP.pyi3
-rw-r--r--frozen_deps/Cryptodome/Math/_IntegerNative.py380
-rw-r--r--frozen_deps/Cryptodome/Math/_IntegerNative.pyi3
-rw-r--r--frozen_deps/Cryptodome/Math/__init__.py0
-rwxr-xr-xfrozen_deps/Cryptodome/Math/_modexp.cpython-38-x86_64-linux-gnu.sobin0 -> 207274 bytes
-rw-r--r--frozen_deps/Cryptodome/Protocol/KDF.py574
-rw-r--r--frozen_deps/Cryptodome/Protocol/KDF.pyi24
-rw-r--r--frozen_deps/Cryptodome/Protocol/SecretSharing.py278
-rw-r--r--frozen_deps/Cryptodome/Protocol/SecretSharing.pyi22
-rw-r--r--frozen_deps/Cryptodome/Protocol/__init__.py31
-rw-r--r--frozen_deps/Cryptodome/Protocol/__init__.pyi1
-rwxr-xr-xfrozen_deps/Cryptodome/Protocol/_scrypt.cpython-38-x86_64-linux-gnu.sobin0 -> 16510 bytes
-rw-r--r--frozen_deps/Cryptodome/PublicKey/DSA.py679
-rw-r--r--frozen_deps/Cryptodome/PublicKey/DSA.pyi30
-rw-r--r--frozen_deps/Cryptodome/PublicKey/ECC.py1184
-rw-r--r--frozen_deps/Cryptodome/PublicKey/ECC.pyi62
-rw-r--r--frozen_deps/Cryptodome/PublicKey/ElGamal.py286
-rw-r--r--frozen_deps/Cryptodome/PublicKey/ElGamal.pyi18
-rw-r--r--frozen_deps/Cryptodome/PublicKey/RSA.py796
-rw-r--r--frozen_deps/Cryptodome/PublicKey/RSA.pyi50
-rw-r--r--frozen_deps/Cryptodome/PublicKey/__init__.py95
-rw-r--r--frozen_deps/Cryptodome/PublicKey/__init__.pyi0
-rwxr-xr-xfrozen_deps/Cryptodome/PublicKey/_ec_ws.cpython-38-x86_64-linux-gnu.sobin0 -> 1000375 bytes
-rw-r--r--frozen_deps/Cryptodome/PublicKey/_openssh.py135
-rw-r--r--frozen_deps/Cryptodome/PublicKey/_openssh.pyi7
-rw-r--r--frozen_deps/Cryptodome/Random/__init__.py57
-rw-r--r--frozen_deps/Cryptodome/Random/__init__.pyi19
-rw-r--r--frozen_deps/Cryptodome/Random/random.py138
-rw-r--r--frozen_deps/Cryptodome/Random/random.pyi20
-rw-r--r--frozen_deps/Cryptodome/Signature/DSS.py413
-rw-r--r--frozen_deps/Cryptodome/Signature/DSS.pyi27
-rw-r--r--frozen_deps/Cryptodome/Signature/PKCS1_PSS.py55
-rw-r--r--frozen_deps/Cryptodome/Signature/PKCS1_PSS.pyi7
-rw-r--r--frozen_deps/Cryptodome/Signature/PKCS1_v1_5.py53
-rw-r--r--frozen_deps/Cryptodome/Signature/PKCS1_v1_5.pyi6
-rw-r--r--frozen_deps/Cryptodome/Signature/__init__.py36
-rw-r--r--frozen_deps/Cryptodome/Signature/pkcs1_15.py222
-rw-r--r--frozen_deps/Cryptodome/Signature/pkcs1_15.pyi17
-rw-r--r--frozen_deps/Cryptodome/Signature/pss.py386
-rw-r--r--frozen_deps/Cryptodome/Signature/pss.pyi30
-rw-r--r--frozen_deps/Cryptodome/Util/Counter.py70
-rw-r--r--frozen_deps/Cryptodome/Util/Counter.pyi5
-rw-r--r--frozen_deps/Cryptodome/Util/Padding.py106
-rw-r--r--frozen_deps/Cryptodome/Util/Padding.pyi6
-rw-r--r--frozen_deps/Cryptodome/Util/RFC1751.py386
-rw-r--r--frozen_deps/Cryptodome/Util/RFC1751.pyi7
-rw-r--r--frozen_deps/Cryptodome/Util/__init__.py41
-rw-r--r--frozen_deps/Cryptodome/Util/_cpu_features.py46
-rw-r--r--frozen_deps/Cryptodome/Util/_cpu_features.pyi2
-rwxr-xr-xfrozen_deps/Cryptodome/Util/_cpuid_c.cpython-38-x86_64-linux-gnu.sobin0 -> 10899 bytes
-rw-r--r--frozen_deps/Cryptodome/Util/_file_system.py54
-rw-r--r--frozen_deps/Cryptodome/Util/_file_system.pyi4
-rw-r--r--frozen_deps/Cryptodome/Util/_raw_api.py327
-rw-r--r--frozen_deps/Cryptodome/Util/_raw_api.pyi27
-rwxr-xr-xfrozen_deps/Cryptodome/Util/_strxor.cpython-38-x86_64-linux-gnu.sobin0 -> 13213 bytes
-rw-r--r--frozen_deps/Cryptodome/Util/asn1.py940
-rw-r--r--frozen_deps/Cryptodome/Util/asn1.pyi74
-rw-r--r--frozen_deps/Cryptodome/Util/number.py1469
-rw-r--r--frozen_deps/Cryptodome/Util/number.pyi19
-rw-r--r--frozen_deps/Cryptodome/Util/py3compat.py164
-rw-r--r--frozen_deps/Cryptodome/Util/py3compat.pyi35
-rw-r--r--frozen_deps/Cryptodome/Util/strxor.py137
-rw-r--r--frozen_deps/Cryptodome/Util/strxor.pyi6
-rw-r--r--frozen_deps/Cryptodome/__init__.py6
-rw-r--r--frozen_deps/Cryptodome/__init__.pyi4
-rw-r--r--frozen_deps/Cryptodome/py.typed0
212 files changed, 24798 insertions, 0 deletions
diff --git a/frozen_deps/Cryptodome/Cipher/AES.py b/frozen_deps/Cryptodome/Cipher/AES.py
new file mode 100644
index 0000000..dd2671a
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/AES.py
@@ -0,0 +1,250 @@
+# -*- coding: utf-8 -*-
+#
+# Cipher/AES.py : AES
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+"""
+Module's constants for the modes of operation supported with AES:
+
+:var MODE_ECB: :ref:`Electronic Code Book (ECB) <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_CCM: :ref:`Counter with CBC-MAC (CCM) Mode <ccm_mode>`
+:var MODE_EAX: :ref:`EAX Mode <eax_mode>`
+:var MODE_GCM: :ref:`Galois Counter Mode (GCM) <gcm_mode>`
+:var MODE_SIV: :ref:`Syntethic Initialization Vector (SIV) <siv_mode>`
+:var MODE_OCB: :ref:`Offset Code Book (OCB) <ocb_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)
+
+from Cryptodome.Util import _cpu_features
+from Cryptodome.Random import get_random_bytes
+
+
+_cproto = """
+ int AES_start_operation(const uint8_t key[],
+ size_t key_len,
+ void **pResult);
+ int AES_encrypt(const void *state,
+ const uint8_t *in,
+ uint8_t *out,
+ size_t data_len);
+ int AES_decrypt(const void *state,
+ const uint8_t *in,
+ uint8_t *out,
+ size_t data_len);
+ int AES_stop_operation(void *state);
+ """
+
+
+# Load portable AES
+_raw_aes_lib = load_pycryptodome_raw_lib("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.
+
+ :param key:
+ The secret key to use in the symmetric cipher.
+
+ It must be 16, 24 or 32 bytes long (respectively for *AES-128*,
+ *AES-192* or *AES-256*).
+
+ For ``MODE_SIV`` only, it doubles to 32, 48, or 64 bytes.
+ :type key: bytes/bytearray/memoryview
+
+ :param mode:
+ The chaining mode to use for encryption or decryption.
+ If in doubt, use ``MODE_EAX``.
+ :type mode: One of the supported ``MODE_*`` constants
+
+ :Keyword Arguments:
+ * **iv** (*bytes*, *bytearray*, *memoryview*) --
+ (Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``,
+ and ``MODE_OPENPGP`` modes).
+
+ The initialization vector to use for encryption or decryption.
+
+ For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 16 bytes long.
+
+ For ``MODE_OPENPGP`` mode only,
+ it must be 16 bytes long for encryption
+ and 18 bytes for decryption (in the latter case, it is
+ actually the *encrypted* IV which was prefixed to the ciphertext).
+
+ If not provided, a random byte string is generated (you must then
+ read its value with the :attr:`iv` attribute).
+
+ * **nonce** (*bytes*, *bytearray*, *memoryview*) --
+ (Only applicable for ``MODE_CCM``, ``MODE_EAX``, ``MODE_GCM``,
+ ``MODE_SIV``, ``MODE_OCB``, and ``MODE_CTR``).
+
+ A value that must never be reused for any other encryption done
+ with this key (except possibly for ``MODE_SIV``, see below).
+
+ For ``MODE_EAX``, ``MODE_GCM`` and ``MODE_SIV`` there are no
+ restrictions on its length (recommended: **16** bytes).
+
+ For ``MODE_CCM``, its length must be in the range **[7..13]**.
+ Bear in mind that with CCM there is a trade-off between nonce
+ length and maximum message size. Recommendation: **11** bytes.
+
+ For ``MODE_OCB``, its length must be in the range **[1..15]**
+ (recommended: **15**).
+
+ For ``MODE_CTR``, its length must be in the range **[0..15]**
+ (recommended: **8**).
+
+ For ``MODE_SIV``, the nonce is optional, if it is not specified,
+ then no nonce is being used, which renders the encryption
+ deterministic.
+
+ If not provided, for modes other than ``MODE_SIV```, a random
+ byte string of the recommended length is used (you must then
+ read its value with the :attr:`nonce` attribute).
+
+ * **segment_size** (*integer*) --
+ (Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext
+ are segmented in. It must be a multiple of 8.
+ If not specified, it will be assumed to be 8.
+
+ * **mac_len** : (*integer*) --
+ (Only ``MODE_EAX``, ``MODE_GCM``, ``MODE_OCB``, ``MODE_CCM``)
+ Length of the authentication tag, in bytes.
+
+ It must be even and in the range **[4..16]**.
+ The recommended value (and the default, if not specified) is **16**.
+
+ * **msg_len** : (*integer*) --
+ (Only ``MODE_CCM``). Length of the message to (de)cipher.
+ If not specified, ``encrypt`` must be called with the entire message.
+ Similarly, ``decrypt`` can only be called once.
+
+ * **assoc_len** : (*integer*) --
+ (Only ``MODE_CCM``). Length of the associated data.
+ If not specified, all associated data is buffered internally,
+ which may represent a problem for very large messages.
+
+ * **initial_value** : (*integer* or *bytes/bytearray/memoryview*) --
+ (Only ``MODE_CTR``).
+ The initial value for the counter. If not present, the cipher will
+ start counting from 0. The value is incremented by one for each block.
+ The counter number is encoded in big endian mode.
+
+ * **counter** : (*object*) --
+ Instance of ``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).
+
+ :Return: an AES object, of the applicable mode.
+ """
+
+ kwargs["add_aes_modes"] = True
+ return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
+
+
+MODE_ECB = 1
+MODE_CBC = 2
+MODE_CFB = 3
+MODE_OFB = 5
+MODE_CTR = 6
+MODE_OPENPGP = 7
+MODE_CCM = 8
+MODE_EAX = 9
+MODE_SIV = 10
+MODE_GCM = 11
+MODE_OCB = 12
+
+# Size of a data block (in bytes)
+block_size = 16
+# Size of a key (in bytes)
+key_size = (16, 24, 32)
diff --git a/frozen_deps/Cryptodome/Cipher/AES.pyi b/frozen_deps/Cryptodome/Cipher/AES.pyi
new file mode 100644
index 0000000..c150efb
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/AES.pyi
@@ -0,0 +1,47 @@
+from typing import Union, Tuple, Optional, Dict
+
+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
+
+AESMode = int
+
+MODE_ECB: AESMode
+MODE_CBC: AESMode
+MODE_CFB: AESMode
+MODE_OFB: AESMode
+MODE_CTR: AESMode
+MODE_OPENPGP: AESMode
+MODE_CCM: AESMode
+MODE_EAX: AESMode
+MODE_GCM: AESMode
+MODE_SIV: AESMode
+MODE_OCB: AESMode
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+def new(key: Buffer,
+ mode: AESMode,
+ iv : Buffer = ...,
+ IV : Buffer = ...,
+ nonce : Buffer = ...,
+ segment_size : int = ...,
+ mac_len : int = ...,
+ assoc_len : int = ...,
+ initial_value : Union[int, Buffer] = ...,
+ counter : Dict = ...,
+ use_aesni : bool = ...) -> \
+ Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode,
+ OpenPgpMode, CcmMode, EaxMode, GcmMode,
+ SivMode, OcbMode]: ...
+
+block_size: int
+key_size: Tuple[int, int, int]
diff --git a/frozen_deps/Cryptodome/Cipher/ARC2.py b/frozen_deps/Cryptodome/Cipher/ARC2.py
new file mode 100644
index 0000000..4dc1bb8
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/ARC2.py
@@ -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)
diff --git a/frozen_deps/Cryptodome/Cipher/ARC2.pyi b/frozen_deps/Cryptodome/Cipher/ARC2.pyi
new file mode 100644
index 0000000..9659c68
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/ARC2.pyi
@@ -0,0 +1,35 @@
+from typing import Union, Dict, Iterable
+
+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
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+def new(key: Buffer,
+ mode: ARC2Mode,
+ iv : Buffer = ...,
+ IV : Buffer = ...,
+ nonce : Buffer = ...,
+ segment_size : int = ...,
+ mac_len : int = ...,
+ initial_value : Union[int, Buffer] = ...,
+ counter : Dict = ...) -> \
+ Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ...
+
+block_size: int
+key_size: Iterable[int]
diff --git a/frozen_deps/Cryptodome/Cipher/ARC4.py b/frozen_deps/Cryptodome/Cipher/ARC4.py
new file mode 100644
index 0000000..e640e77
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/ARC4.py
@@ -0,0 +1,137 @@
+# -*- 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.py3compat import b
+
+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 ``[5..256]``.
+ The recommended length is 16 bytes.
+ :type key: bytes, bytearray, memoryview
+
+ :Keyword Arguments:
+ * *drop* (``integer``) --
+ The amount of bytes to discard from the initial part of the keystream.
+ In fact, such part has been found to be distinguishable from random
+ data (while it shouldn't) and also correlated to key.
+
+ The recommended value is 3072_ bytes. The default value is 0.
+
+ :Return: an `ARC4Cipher` object
+
+ .. _3072: http://eprint.iacr.org/2002/067.pdf
+ """
+ return ARC4Cipher(key, *args, **kwargs)
+
+# Size of a data block (in bytes)
+block_size = 1
+# Size of a key (in bytes)
+key_size = range(5, 256+1)
diff --git a/frozen_deps/Cryptodome/Cipher/ARC4.pyi b/frozen_deps/Cryptodome/Cipher/ARC4.pyi
new file mode 100644
index 0000000..2e75d6f
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/ARC4.pyi
@@ -0,0 +1,16 @@
+from typing import Any, Union, Iterable
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class ARC4Cipher:
+ block_size: int
+ key_size: int
+
+ def __init__(self, key: Buffer, *args: Any, **kwargs: Any) -> None: ...
+ def encrypt(self, plaintext: Buffer) -> bytes: ...
+ def decrypt(self, ciphertext: Buffer) -> bytes: ...
+
+def new(key: Buffer, drop : int = ...) -> ARC4Cipher: ...
+
+block_size: int
+key_size: Iterable[int]
diff --git a/frozen_deps/Cryptodome/Cipher/Blowfish.py b/frozen_deps/Cryptodome/Cipher/Blowfish.py
new file mode 100644
index 0000000..536cbc8
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/Blowfish.py
@@ -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)
diff --git a/frozen_deps/Cryptodome/Cipher/Blowfish.pyi b/frozen_deps/Cryptodome/Cipher/Blowfish.pyi
new file mode 100644
index 0000000..a669240
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/Blowfish.pyi
@@ -0,0 +1,35 @@
+from typing import Union, Dict, Iterable
+
+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
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+def new(key: Buffer,
+ mode: BlowfishMode,
+ iv : Buffer = ...,
+ IV : Buffer = ...,
+ nonce : Buffer = ...,
+ segment_size : int = ...,
+ mac_len : int = ...,
+ initial_value : Union[int, Buffer] = ...,
+ counter : Dict = ...) -> \
+ Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ...
+
+block_size: int
+key_size: Iterable[int]
diff --git a/frozen_deps/Cryptodome/Cipher/CAST.py b/frozen_deps/Cryptodome/Cipher/CAST.py
new file mode 100644
index 0000000..84eb88e
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/CAST.py
@@ -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)
diff --git a/frozen_deps/Cryptodome/Cipher/CAST.pyi b/frozen_deps/Cryptodome/Cipher/CAST.pyi
new file mode 100644
index 0000000..6b411cf
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/CAST.pyi
@@ -0,0 +1,35 @@
+from typing import Union, Dict, Iterable
+
+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
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+def new(key: Buffer,
+ mode: CASTMode,
+ iv : Buffer = ...,
+ IV : Buffer = ...,
+ nonce : Buffer = ...,
+ segment_size : int = ...,
+ mac_len : int = ...,
+ initial_value : Union[int, Buffer] = ...,
+ counter : Dict = ...) -> \
+ Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ...
+
+block_size: int
+key_size : Iterable[int]
diff --git a/frozen_deps/Cryptodome/Cipher/ChaCha20.py b/frozen_deps/Cryptodome/Cipher/ChaCha20.py
new file mode 100644
index 0000000..0cd9102
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/ChaCha20.py
@@ -0,0 +1,286 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# 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."""
+
+ # 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"
+
+ self.nonce = _copy_bytes(None, None, nonce)
+
+ self._next = ( self.encrypt, self.decrypt )
+
+ self._state = VoidPointer()
+ result = _raw_chacha20_lib.chacha20_init(
+ self._state.address_of(),
+ c_uint8_ptr(key),
+ c_size_t(len(key)),
+ self.nonce,
+ c_size_t(len(nonce)))
+ if result:
+ raise ValueError("Error %d instantiating a %s cipher" % (result,
+ self._name))
+ self._state = SmartPointer(self._state.get(),
+ _raw_chacha20_lib.chacha20_destroy)
+
+ def encrypt(self, plaintext, output=None):
+ """Encrypt a piece of data.
+
+ Args:
+ plaintext(bytes/bytearray/memoryview): The data to encrypt, of any size.
+ Keyword Args:
+ output(bytes/bytearray/memoryview): The location where the ciphertext
+ is written to. If ``None``, the ciphertext is returned.
+ Returns:
+ If ``output`` is ``None``, the ciphertext is returned as ``bytes``.
+ Otherwise, ``None``.
+ """
+
+ if self.encrypt not in self._next:
+ raise TypeError("Cipher object can only be used for decryption")
+ self._next = ( self.encrypt, )
+ return self._encrypt(plaintext, output)
+
+ def _encrypt(self, plaintext, output):
+ """Encrypt without FSM checks"""
+
+ if output is None:
+ ciphertext = create_string_buffer(len(plaintext))
+ else:
+ ciphertext = output
+
+ if not is_writeable_buffer(output):
+ raise TypeError("output must be a bytearray or a writeable memoryview")
+
+ if len(plaintext) != len(output):
+ raise ValueError("output must have the same length as the input"
+ " (%d bytes)" % len(plaintext))
+
+ result = _raw_chacha20_lib.chacha20_encrypt(
+ self._state.get(),
+ c_uint8_ptr(plaintext),
+ c_uint8_ptr(ciphertext),
+ c_size_t(len(plaintext)))
+ if result:
+ raise ValueError("Error %d while encrypting with %s" % (result, self._name))
+
+ if output is None:
+ return get_raw_buffer(ciphertext)
+ else:
+ return None
+
+ def decrypt(self, ciphertext, output=None):
+ """Decrypt a piece of data.
+
+ Args:
+ ciphertext(bytes/bytearray/memoryview): The data to decrypt, of any size.
+ Keyword Args:
+ output(bytes/bytearray/memoryview): The location where the plaintext
+ is written to. If ``None``, the plaintext is returned.
+ Returns:
+ If ``output`` is ``None``, the plaintext is returned as ``bytes``.
+ Otherwise, ``None``.
+ """
+
+ if self.decrypt not in self._next:
+ raise TypeError("Cipher object can only be used for encryption")
+ self._next = ( self.decrypt, )
+
+ try:
+ return self._encrypt(ciphertext, output)
+ except ValueError as e:
+ raise ValueError(str(e).replace("enc", "dec"))
+
+ def seek(self, position):
+ """Seek to a certain position in the key stream.
+
+ Args:
+ position (integer):
+ The absolute position within the key stream, in bytes.
+ """
+
+ position, offset = divmod(position, 64)
+ block_low = position & 0xFFFFFFFF
+ block_high = position >> 32
+
+ result = _raw_chacha20_lib.chacha20_seek(
+ self._state.get(),
+ c_ulong(block_high),
+ c_ulong(block_low),
+ offset
+ )
+ if result:
+ raise ValueError("Error %d while seeking with %s" % (result, self._name))
+
+
+def _derive_Poly1305_key_pair(key, nonce):
+ """Derive a tuple (r, s, nonce) for a Poly1305 MAC.
+
+ If nonce is ``None``, a new 12-byte nonce is generated.
+ """
+
+ if len(key) != 32:
+ raise ValueError("Poly1305 with ChaCha20 requires a 32-byte key")
+
+ if nonce is None:
+ padded_nonce = nonce = get_random_bytes(12)
+ elif len(nonce) == 8:
+ # See RFC7538, 2.6: [...] ChaCha20 as specified here requires a 96-bit
+ # nonce. So if the provided nonce is only 64-bit, then the first 32
+ # bits of the nonce will be set to a constant number.
+ # This will usually be zero, but for protocols with multiple senders it may be
+ # different for each sender, but should be the same for all
+ # invocations of the function with the same key by a particular
+ # sender.
+ padded_nonce = b'\x00\x00\x00\x00' + nonce
+ elif len(nonce) == 12:
+ padded_nonce = nonce
+ else:
+ raise ValueError("Poly1305 with ChaCha20 requires an 8- or 12-byte nonce")
+
+ rs = new(key=key, nonce=padded_nonce).encrypt(b'\x00' * 32)
+ return rs[:16], rs[16:], nonce
+
+
+def new(**kwargs):
+ """Create a new ChaCha20 or XChaCha20 cipher
+
+ Keyword Args:
+ key (bytes/bytearray/memoryview): The secret key to use.
+ It must be 32 bytes long.
+ nonce (bytes/bytearray/memoryview): A mandatory value that
+ must never be reused for any other encryption
+ done with this key.
+
+ For ChaCha20, it must be 8 or 12 bytes long.
+
+ For XChaCha20, it must be 24 bytes long.
+
+ If not provided, 8 bytes will be randomly generated
+ (you can find them back in the ``nonce`` attribute).
+
+ :Return: a :class:`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
diff --git a/frozen_deps/Cryptodome/Cipher/ChaCha20.pyi b/frozen_deps/Cryptodome/Cipher/ChaCha20.pyi
new file mode 100644
index 0000000..3d00a1d
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/ChaCha20.pyi
@@ -0,0 +1,25 @@
+from typing import Union, overload
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+def _HChaCha20(key: Buffer, nonce: Buffer) -> bytearray: ...
+
+class ChaCha20Cipher:
+ block_size: int
+ nonce: bytes
+
+ def __init__(self, key: Buffer, nonce: Buffer) -> None: ...
+ @overload
+ def encrypt(self, plaintext: Buffer) -> bytes: ...
+ @overload
+ def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+ @overload
+ def decrypt(self, plaintext: Buffer) -> bytes: ...
+ @overload
+ def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+ def seek(self, position: int) -> None: ...
+
+def new(key: Buffer, nonce: Buffer = ...) -> ChaCha20Cipher: ...
+
+block_size: int
+key_size: int
diff --git a/frozen_deps/Cryptodome/Cipher/ChaCha20_Poly1305.py b/frozen_deps/Cryptodome/Cipher/ChaCha20_Poly1305.py
new file mode 100644
index 0000000..b6bc7a6
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/ChaCha20_Poly1305.py
@@ -0,0 +1,336 @@
+# ===================================================================
+#
+# Copyright (c) 2018, Helder Eijs <[email protected]>
+# 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.nonce = _copy_bytes(None, None, nonce)
+
+ self._next = (self.update, self.encrypt, self.decrypt, self.digest,
+ self.verify)
+
+ self._authenticator = Poly1305.new(key=key, nonce=nonce, cipher=ChaCha20)
+
+ self._cipher = ChaCha20.new(key=key, nonce=nonce)
+ self._cipher.seek(64) # Block counter starts at 1
+
+ self._len_aad = 0
+ self._len_ct = 0
+ self._mac_tag = None
+ self._status = _CipherStatus.PROCESSING_AUTH_DATA
+
+ def update(self, data):
+ """Protect the associated data.
+
+ Associated data (also known as *additional authenticated data* - AAD)
+ is the piece of the message that must stay in the clear, while
+ still allowing the receiver to verify its integrity.
+ An example is packet headers.
+
+ The associated data (possibly split into multiple segments) is
+ fed into :meth:`update` before any call to :meth:`decrypt` or :meth:`encrypt`.
+ If there is no associated data, :meth:`update` is not called.
+
+ :param bytes/bytearray/memoryview assoc_data:
+ A piece of associated data. There are no restrictions on its size.
+ """
+
+ if self.update not in self._next:
+ raise TypeError("update() method cannot be called")
+
+ self._len_aad += len(data)
+ self._authenticator.update(data)
+
+ def _pad_aad(self):
+
+ assert(self._status == _CipherStatus.PROCESSING_AUTH_DATA)
+ if self._len_aad & 0x0F:
+ self._authenticator.update(b'\x00' * (16 - (self._len_aad & 0x0F)))
+ self._status = _CipherStatus.PROCESSING_CIPHERTEXT
+
+ def encrypt(self, plaintext, output=None):
+ """Encrypt a piece of data.
+
+ Args:
+ plaintext(bytes/bytearray/memoryview): The data to encrypt, of any size.
+ Keyword Args:
+ output(bytes/bytearray/memoryview): The location where the ciphertext
+ is written to. If ``None``, the ciphertext is returned.
+ Returns:
+ If ``output`` is ``None``, the ciphertext is returned as ``bytes``.
+ Otherwise, ``None``.
+ """
+
+ if self.encrypt not in self._next:
+ raise TypeError("encrypt() method cannot be called")
+
+ if self._status == _CipherStatus.PROCESSING_AUTH_DATA:
+ self._pad_aad()
+
+ self._next = (self.encrypt, self.digest)
+
+ result = self._cipher.encrypt(plaintext, output=output)
+ self._len_ct += len(plaintext)
+ if output is None:
+ self._authenticator.update(result)
+ else:
+ self._authenticator.update(output)
+ return result
+
+ def decrypt(self, ciphertext, output=None):
+ """Decrypt a piece of data.
+
+ Args:
+ ciphertext(bytes/bytearray/memoryview): The data to decrypt, of any size.
+ Keyword Args:
+ output(bytes/bytearray/memoryview): The location where the plaintext
+ is written to. If ``None``, the plaintext is returned.
+ Returns:
+ If ``output`` is ``None``, the plaintext is returned as ``bytes``.
+ Otherwise, ``None``.
+ """
+
+ if self.decrypt not in self._next:
+ raise TypeError("decrypt() method cannot be called")
+
+ if self._status == _CipherStatus.PROCESSING_AUTH_DATA:
+ self._pad_aad()
+
+ self._next = (self.decrypt, self.verify)
+
+ self._len_ct += len(ciphertext)
+ self._authenticator.update(ciphertext)
+ return self._cipher.decrypt(ciphertext, output=output)
+
+ def _compute_mac(self):
+ """Finalize the cipher (if not done already) and return the MAC."""
+
+ if self._mac_tag:
+ assert(self._status == _CipherStatus.PROCESSING_DONE)
+ return self._mac_tag
+
+ assert(self._status != _CipherStatus.PROCESSING_DONE)
+
+ if self._status == _CipherStatus.PROCESSING_AUTH_DATA:
+ self._pad_aad()
+
+ if self._len_ct & 0x0F:
+ self._authenticator.update(b'\x00' * (16 - (self._len_ct & 0x0F)))
+
+ self._status = _CipherStatus.PROCESSING_DONE
+
+ self._authenticator.update(long_to_bytes(self._len_aad, 8)[::-1])
+ self._authenticator.update(long_to_bytes(self._len_ct, 8)[::-1])
+ self._mac_tag = self._authenticator.digest()
+ return self._mac_tag
+
+ def digest(self):
+ """Compute the *binary* authentication tag (MAC).
+
+ :Return: the MAC tag, as 16 ``bytes``.
+ """
+
+ if self.digest not in self._next:
+ raise TypeError("digest() method cannot be called")
+ self._next = (self.digest,)
+
+ return self._compute_mac()
+
+ def hexdigest(self):
+ """Compute the *printable* authentication tag (MAC).
+
+ This method is like :meth:`digest`.
+
+ :Return: the MAC tag, as a hexadecimal string.
+ """
+ return "".join(["%02x" % bord(x) for x in self.digest()])
+
+ def verify(self, received_mac_tag):
+ """Validate the *binary* authentication tag (MAC).
+
+ The receiver invokes this method at the very end, to
+ check if the associated data (if any) and the decrypted
+ messages are valid.
+
+ :param bytes/bytearray/memoryview received_mac_tag:
+ This is the 16-byte *binary* MAC, as received from the sender.
+ :Raises ValueError:
+ if the MAC does not match. The message has been tampered with
+ or the key is incorrect.
+ """
+
+ if self.verify not in self._next:
+ raise TypeError("verify() cannot be called"
+ " when encrypting a message")
+ self._next = (self.verify,)
+
+ secret = get_random_bytes(16)
+
+ self._compute_mac()
+
+ mac1 = BLAKE2s.new(digest_bits=160, key=secret,
+ data=self._mac_tag)
+ mac2 = BLAKE2s.new(digest_bits=160, key=secret,
+ data=received_mac_tag)
+
+ if mac1.digest() != mac2.digest():
+ raise ValueError("MAC check failed")
+
+ def hexverify(self, hex_mac_tag):
+ """Validate the *printable* authentication tag (MAC).
+
+ This method is like :meth:`verify`.
+
+ :param string hex_mac_tag:
+ This is the *printable* MAC.
+ :Raises ValueError:
+ if the MAC does not match. The message has been tampered with
+ or the key is incorrect.
+ """
+
+ self.verify(unhexlify(hex_mac_tag))
+
+ def encrypt_and_digest(self, plaintext):
+ """Perform :meth:`encrypt` and :meth:`digest` in one step.
+
+ :param plaintext: The data to encrypt, of any size.
+ :type plaintext: bytes/bytearray/memoryview
+ :return: a tuple with two ``bytes`` objects:
+
+ - the ciphertext, of equal length as the plaintext
+ - the 16-byte MAC tag
+ """
+
+ return self.encrypt(plaintext), self.digest()
+
+ def decrypt_and_verify(self, ciphertext, received_mac_tag):
+ """Perform :meth:`decrypt` and :meth:`verify` in one step.
+
+ :param ciphertext: The piece of data to decrypt.
+ :type ciphertext: bytes/bytearray/memoryview
+ :param bytes received_mac_tag:
+ This is the 16-byte *binary* MAC, as received from the sender.
+ :return: the decrypted data (as ``bytes``)
+ :raises ValueError:
+ if the MAC does not match. The message has been tampered with
+ or the key is incorrect.
+ """
+
+ plaintext = self.decrypt(ciphertext)
+ self.verify(received_mac_tag)
+ return plaintext
+
+
+def new(**kwargs):
+ """Create a new ChaCha20-Poly1305 or XChaCha20-Poly1305 AEAD cipher.
+
+ :keyword key: The secret key to use. It must be 32 bytes long.
+ :type key: byte string
+
+ :keyword nonce:
+ A value that must never be reused for any other encryption
+ done with this key.
+
+ For ChaCha20-Poly1305, it must be 8 or 12 bytes long.
+
+ For XChaCha20-Poly1305, it must be 24 bytes long.
+
+ If not provided, 12 ``bytes`` will be generated randomly
+ (you can find them back in the ``nonce`` attribute).
+ :type nonce: bytes, bytearray, memoryview
+
+ :Return: a :class:`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):
+ pass
+ elif len(nonce) == 24:
+ key = _HChaCha20(key, nonce[:16])
+ nonce = b'\x00\x00\x00\x00' + nonce[16:]
+ else:
+ raise ValueError("Nonce must be 8, 12 or 24 bytes long")
+
+ if not is_buffer(nonce):
+ raise TypeError("nonce must be bytes, bytearray or memoryview")
+
+ if kwargs:
+ raise TypeError("Unknown parameters: " + str(kwargs))
+
+ return ChaCha20Poly1305Cipher(key, nonce)
+
+
+# Size of a key (in bytes)
+key_size = 32
diff --git a/frozen_deps/Cryptodome/Cipher/ChaCha20_Poly1305.pyi b/frozen_deps/Cryptodome/Cipher/ChaCha20_Poly1305.pyi
new file mode 100644
index 0000000..ef0450f
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/ChaCha20_Poly1305.pyi
@@ -0,0 +1,28 @@
+from typing import Union, Tuple, overload
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class ChaCha20Poly1305Cipher:
+ nonce: bytes
+
+ def __init__(self, key: Buffer, nonce: Buffer) -> None: ...
+ def update(self, data: Buffer) -> None: ...
+ @overload
+ def encrypt(self, plaintext: Buffer) -> bytes: ...
+ @overload
+ def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+ @overload
+ def decrypt(self, plaintext: Buffer) -> bytes: ...
+ @overload
+ def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+ def digest(self) -> bytes: ...
+ def hexdigest(self) -> str: ...
+ def verify(self, received_mac_tag: Buffer) -> None: ...
+ def hexverify(self, received_mac_tag: str) -> None: ...
+ def encrypt_and_digest(self, plaintext: Buffer) -> Tuple[bytes, bytes]: ...
+ def decrypt_and_verify(self, ciphertext: Buffer, received_mac_tag: Buffer) -> bytes: ...
+
+def new(key: Buffer, nonce: Buffer = ...) -> ChaCha20Poly1305Cipher: ...
+
+block_size: int
+key_size: int
diff --git a/frozen_deps/Cryptodome/Cipher/DES.py b/frozen_deps/Cryptodome/Cipher/DES.py
new file mode 100644
index 0000000..026b491
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/DES.py
@@ -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
diff --git a/frozen_deps/Cryptodome/Cipher/DES.pyi b/frozen_deps/Cryptodome/Cipher/DES.pyi
new file mode 100644
index 0000000..1ba2752
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/DES.pyi
@@ -0,0 +1,35 @@
+from typing import Union, Dict, Iterable
+
+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
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+def new(key: Buffer,
+ mode: DESMode,
+ iv : Buffer = ...,
+ IV : Buffer = ...,
+ nonce : Buffer = ...,
+ segment_size : int = ...,
+ mac_len : int = ...,
+ initial_value : Union[int, Buffer] = ...,
+ counter : Dict = ...) -> \
+ Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ...
+
+block_size: int
+key_size: int
diff --git a/frozen_deps/Cryptodome/Cipher/DES3.py b/frozen_deps/Cryptodome/Cipher/DES3.py
new file mode 100644
index 0000000..3b2828e
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/DES3.py
@@ -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)
diff --git a/frozen_deps/Cryptodome/Cipher/DES3.pyi b/frozen_deps/Cryptodome/Cipher/DES3.pyi
new file mode 100644
index 0000000..c1a524f
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/DES3.pyi
@@ -0,0 +1,37 @@
+from typing import Union, Dict, Tuple
+
+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
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+def new(key: Buffer,
+ mode: DES3Mode,
+ iv : Buffer = ...,
+ IV : Buffer = ...,
+ nonce : Buffer = ...,
+ segment_size : int = ...,
+ mac_len : int = ...,
+ initial_value : Union[int, Buffer] = ...,
+ counter : Dict = ...) -> \
+ Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode, OpenPgpMode]: ...
+
+block_size: int
+key_size: Tuple[int, int]
diff --git a/frozen_deps/Cryptodome/Cipher/PKCS1_OAEP.py b/frozen_deps/Cryptodome/Cipher/PKCS1_OAEP.py
new file mode 100644
index 0000000..3207bbe
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/PKCS1_OAEP.py
@@ -0,0 +1,239 @@
+# -*- 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 bord, _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
+
+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)
+ m_int = self._key._decrypt(ct_int)
+ # Complete step 2c (I2OSP)
+ em = long_to_bytes(m_int, k)
+ # Step 3a
+ lHash = self._hashObj.new(self._label).digest()
+ # Step 3b
+ y = em[0]
+ # 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 3g
+ one_pos = db[hLen:].find(b'\x01')
+ lHash1 = db[:hLen]
+ invalid = bord(y) | int(one_pos < 0)
+ hash_compare = strxor(lHash1, lHash)
+ for x in hash_compare:
+ invalid |= bord(x)
+ for x in db[hLen:one_pos]:
+ invalid |= bord(x)
+ if invalid != 0:
+ raise ValueError("Incorrect decryption.")
+ # Step 4
+ return db[hLen + one_pos + 1:]
+
+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)
+
diff --git a/frozen_deps/Cryptodome/Cipher/PKCS1_OAEP.pyi b/frozen_deps/Cryptodome/Cipher/PKCS1_OAEP.pyi
new file mode 100644
index 0000000..b54cd3f
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/PKCS1_OAEP.pyi
@@ -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: ...
diff --git a/frozen_deps/Cryptodome/Cipher/PKCS1_v1_5.py b/frozen_deps/Cryptodome/Cipher/PKCS1_v1_5.py
new file mode 100644
index 0000000..1fd1626
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/PKCS1_v1_5.py
@@ -0,0 +1,199 @@
+# -*- 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.Util.number import ceil_div, bytes_to_long, long_to_bytes
+from Cryptodome.Util.py3compat import bord, _copy_bytes
+import Cryptodome.Util.number
+from Cryptodome import Random
+
+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
+ modBits = Cryptodome.Util.number.size(self._key.n)
+ k = ceil_div(modBits,8) # Convert from bits to bytes
+ mLen = len(message)
+
+ # Step 1
+ if mLen > k - 11:
+ raise ValueError("Plaintext is too long.")
+ # Step 2a
+ ps = []
+ while len(ps) != k - mLen - 3:
+ new_byte = self._randfunc(1)
+ if bord(new_byte[0]) == 0x00:
+ continue
+ ps.append(new_byte)
+ ps = b"".join(ps)
+ assert(len(ps) == k - mLen - 3)
+ # Step 2b
+ em = b'\x00\x02' + ps + b'\x00' + _copy_bytes(None, None, message)
+ # Step 3a (OS2IP)
+ em_int = bytes_to_long(em)
+ # Step 3b (RSAEP)
+ m_int = self._key._encrypt(em_int)
+ # Step 3c (I2OSP)
+ c = long_to_bytes(m_int, k)
+ return c
+
+ def decrypt(self, ciphertext, sentinel):
+ r"""Decrypt a PKCS#1 v1.5 ciphertext.
+
+ This function is named ``RSAES-PKCS1-V1_5-DECRYPT``, and is specified in
+ `section 7.2.2 of RFC8017
+ <https://tools.ietf.org/html/rfc8017#page-29>`_.
+
+ :param ciphertext:
+ The ciphertext that contains the message to recover.
+ :type ciphertext: bytes/bytearray/memoryview
+
+ :param sentinel:
+ The object to return whenever an error is detected.
+ :type sentinel: any type
+
+ :Returns: A byte string. It is either the original message or the ``sentinel`` (in case of an error).
+
+ :Raises ValueError:
+ If the ciphertext length is incorrect
+ :Raises TypeError:
+ If the RSA key has no private half (i.e. it cannot be used for
+ decyption).
+
+ .. warning::
+ You should **never** let the party who submitted the ciphertext know that
+ this function returned the ``sentinel`` value.
+ Armed with such knowledge (for a fair amount of carefully crafted but invalid ciphertexts),
+ an attacker is able to recontruct the plaintext of any other encryption that were carried out
+ with the same RSA public key (see `Bleichenbacher's`__ attack).
+
+ In general, it should not be possible for the other party to distinguish
+ whether processing at the server side failed because the value returned
+ was a ``sentinel`` as opposed to a random, invalid message.
+
+ In fact, the second option is not that unlikely: encryption done according to PKCS#1 v1.5
+ embeds no good integrity check. There is roughly one chance
+ in 2\ :sup:`16` for a random ciphertext to be returned as a valid message
+ (although random looking).
+
+ It is therefore advisabled to:
+
+ 1. Select as ``sentinel`` a value that resembles a plausable random, invalid message.
+ 2. Not report back an error as soon as you detect a ``sentinel`` value.
+ Put differently, you should not explicitly check if the returned value is the ``sentinel`` or not.
+ 3. Cover all possible errors with a single, generic error indicator.
+ 4. Embed into the definition of ``message`` (at the protocol level) a digest (e.g. ``SHA-1``).
+ It is recommended for it to be the rightmost part ``message``.
+ 5. Where possible, monitor the number of errors due to ciphertexts originating from the same party,
+ and slow down the rate of the requests from such party (or even blacklist it altogether).
+
+ **If you are designing a new protocol, consider using the more robust PKCS#1 OAEP.**
+
+ .. __: http://www.bell-labs.com/user/bleichen/papers/pkcs.ps
+
+ """
+
+ # See 7.2.1 in RFC3447
+ modBits = Cryptodome.Util.number.size(self._key.n)
+ k = ceil_div(modBits,8) # Convert from bits to bytes
+
+ # Step 1
+ if len(ciphertext) != k:
+ raise ValueError("Ciphertext with incorrect length.")
+ # Step 2a (O2SIP)
+ ct_int = bytes_to_long(ciphertext)
+ # Step 2b (RSADP)
+ m_int = self._key._decrypt(ct_int)
+ # Complete step 2c (I2OSP)
+ em = long_to_bytes(m_int, k)
+ # Step 3
+ sep = em.find(b'\x00', 2)
+ if not em.startswith(b'\x00\x02') or sep < 10:
+ return sentinel
+ # Step 4
+ return em[sep + 1:]
+
+
+def new(key, randfunc=None):
+ """Create a cipher for performing PKCS#1 v1.5 encryption or decryption.
+
+ :param key:
+ The key to use to encrypt or decrypt the message. This is a `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)
+
diff --git a/frozen_deps/Cryptodome/Cipher/PKCS1_v1_5.pyi b/frozen_deps/Cryptodome/Cipher/PKCS1_v1_5.pyi
new file mode 100644
index 0000000..ff4e3f2
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/PKCS1_v1_5.pyi
@@ -0,0 +1,17 @@
+from typing import Callable, Union, Any, Optional
+
+from Cryptodome.PublicKey.RSA import RsaKey
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class PKCS115_Cipher:
+ def __init__(self,
+ key: RsaKey,
+ randfunc: Callable[[int], bytes]) -> None: ...
+ def can_encrypt(self) -> bool: ...
+ def can_decrypt(self) -> bool: ...
+ def encrypt(self, message: Buffer) -> bytes: ...
+ def decrypt(self, ciphertext: Buffer) -> bytes: ...
+
+def new(key: RsaKey,
+ randfunc: Optional[Callable[[int], bytes]] = ...) -> PKCS115_Cipher: ...
diff --git a/frozen_deps/Cryptodome/Cipher/Salsa20.py b/frozen_deps/Cryptodome/Cipher/Salsa20.py
new file mode 100644
index 0000000..79e6701
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/Salsa20.py
@@ -0,0 +1,167 @@
+# -*- coding: utf-8 -*-
+#
+# Cipher/Salsa20.py : Salsa20 stream cipher (http://cr.yp.to/snuffle.html)
+#
+# Contributed by Fabrizio Tarizzo <[email protected]>.
+#
+# ===================================================================
+# 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)
+
diff --git a/frozen_deps/Cryptodome/Cipher/Salsa20.pyi b/frozen_deps/Cryptodome/Cipher/Salsa20.pyi
new file mode 100644
index 0000000..9178f0d
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/Salsa20.pyi
@@ -0,0 +1,27 @@
+from typing import Union, Tuple, Optional, overload
+
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class Salsa20Cipher:
+ nonce: bytes
+ block_size: int
+ key_size: int
+
+ def __init__(self,
+ key: Buffer,
+ nonce: Buffer) -> None: ...
+ @overload
+ def encrypt(self, plaintext: Buffer) -> bytes: ...
+ @overload
+ def encrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+ @overload
+ def decrypt(self, plaintext: Buffer) -> bytes: ...
+ @overload
+ def decrypt(self, plaintext: Buffer, output: Union[bytearray, memoryview]) -> None: ...
+
+def new(key: Buffer, nonce: Optional[Buffer] = ...) -> Salsa20Cipher: ...
+
+block_size: int
+key_size: Tuple[int, int]
+
diff --git a/frozen_deps/Cryptodome/Cipher/_ARC4.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Cipher/_ARC4.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..e4d89af
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_ARC4.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Cipher/_EKSBlowfish.py b/frozen_deps/Cryptodome/Cipher/_EKSBlowfish.py
new file mode 100644
index 0000000..c1c3249
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_EKSBlowfish.py
@@ -0,0 +1,131 @@
+# ===================================================================
+#
+# Copyright (c) 2019, Legrandin <[email protected]>
+# 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)
diff --git a/frozen_deps/Cryptodome/Cipher/_EKSBlowfish.pyi b/frozen_deps/Cryptodome/Cipher/_EKSBlowfish.pyi
new file mode 100644
index 0000000..49c8448
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_EKSBlowfish.pyi
@@ -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]
diff --git a/frozen_deps/Cryptodome/Cipher/_Salsa20.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Cipher/_Salsa20.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..df9884e
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_Salsa20.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Cipher/__init__.py b/frozen_deps/Cryptodome/Cipher/__init__.py
new file mode 100644
index 0000000..9bf067f
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/__init__.py
@@ -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)
diff --git a/frozen_deps/Cryptodome/Cipher/__init__.pyi b/frozen_deps/Cryptodome/Cipher/__init__.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/__init__.pyi
diff --git a/frozen_deps/Cryptodome/Cipher/_chacha20.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Cipher/_chacha20.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..ded8fd8
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_chacha20.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Cipher/_mode_cbc.py b/frozen_deps/Cryptodome/Cipher/_mode_cbc.py
new file mode 100644
index 0000000..edc29ca
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_mode_cbc.py
@@ -0,0 +1,293 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# 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 = [ self.encrypt, self.decrypt ]
+
+ def encrypt(self, plaintext, output=None):
+ """Encrypt data with the key and the parameters set at initialization.
+
+ A cipher object is stateful: once you have encrypted a message
+ you cannot encrypt (or decrypt) another message using the same
+ object.
+
+ The data to encrypt can be broken up in two or
+ more pieces and `encrypt` can be called multiple times.
+
+ That is, the statement:
+
+ >>> c.encrypt(a) + c.encrypt(b)
+
+ is equivalent to:
+
+ >>> c.encrypt(a+b)
+
+ That also means that you cannot reuse an object for encrypting
+ or decrypting other data with the same key.
+
+ This function does not add any padding to the plaintext.
+
+ :Parameters:
+ plaintext : bytes/bytearray/memoryview
+ The piece of data to encrypt.
+ Its lenght must be multiple of the cipher block size.
+ :Keywords:
+ output : bytearray/memoryview
+ The location where the ciphertext must be written to.
+ If ``None``, the ciphertext is returned.
+ :Return:
+ If ``output`` is ``None``, the ciphertext is returned as ``bytes``.
+ Otherwise, ``None``.
+ """
+
+ if self.encrypt not in self._next:
+ raise TypeError("encrypt() cannot be called after decrypt()")
+ self._next = [ self.encrypt ]
+
+ if output is None:
+ ciphertext = create_string_buffer(len(plaintext))
+ else:
+ ciphertext = output
+
+ if not is_writeable_buffer(output):
+ raise TypeError("output must be a bytearray or a writeable memoryview")
+
+ if len(plaintext) != len(output):
+ raise ValueError("output must have the same length as the input"
+ " (%d bytes)" % len(plaintext))
+
+ result = raw_cbc_lib.CBC_encrypt(self._state.get(),
+ c_uint8_ptr(plaintext),
+ c_uint8_ptr(ciphertext),
+ c_size_t(len(plaintext)))
+ if result:
+ if result == 3:
+ raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size)
+ raise ValueError("Error %d while encrypting in CBC mode" % result)
+
+ if output is None:
+ return get_raw_buffer(ciphertext)
+ else:
+ return None
+
+ def decrypt(self, ciphertext, output=None):
+ """Decrypt data with the key and the parameters set at initialization.
+
+ A cipher object is stateful: once you have decrypted a message
+ you cannot decrypt (or encrypt) another message with the same
+ object.
+
+ The data to decrypt can be broken up in two or
+ more pieces and `decrypt` can be called multiple times.
+
+ That is, the statement:
+
+ >>> c.decrypt(a) + c.decrypt(b)
+
+ is equivalent to:
+
+ >>> c.decrypt(a+b)
+
+ This function does not remove any padding from the plaintext.
+
+ :Parameters:
+ ciphertext : bytes/bytearray/memoryview
+ The piece of data to decrypt.
+ Its length must be multiple of the cipher block size.
+ :Keywords:
+ output : bytearray/memoryview
+ The location where the plaintext must be written to.
+ If ``None``, the plaintext is returned.
+ :Return:
+ If ``output`` is ``None``, the plaintext is returned as ``bytes``.
+ Otherwise, ``None``.
+ """
+
+ if self.decrypt not in self._next:
+ raise TypeError("decrypt() cannot be called after encrypt()")
+ self._next = [ self.decrypt ]
+
+ if output is None:
+ plaintext = create_string_buffer(len(ciphertext))
+ else:
+ plaintext = output
+
+ if not is_writeable_buffer(output):
+ raise TypeError("output must be a bytearray or a writeable memoryview")
+
+ if len(ciphertext) != len(output):
+ raise ValueError("output must have the same length as the input"
+ " (%d bytes)" % len(plaintext))
+
+ result = raw_cbc_lib.CBC_decrypt(self._state.get(),
+ c_uint8_ptr(ciphertext),
+ c_uint8_ptr(plaintext),
+ c_size_t(len(ciphertext)))
+ if result:
+ if result == 3:
+ raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size)
+ raise ValueError("Error %d while decrypting in CBC mode" % result)
+
+ if output is None:
+ return get_raw_buffer(plaintext)
+ else:
+ return None
+
+
+def _create_cbc_cipher(factory, **kwargs):
+ """Instantiate a cipher object that performs CBC encryption/decryption.
+
+ :Parameters:
+ factory : module
+ The underlying block cipher, a module from ``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)
diff --git a/frozen_deps/Cryptodome/Cipher/_mode_cbc.pyi b/frozen_deps/Cryptodome/Cipher/_mode_cbc.pyi
new file mode 100644
index 0000000..526632e
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_mode_cbc.pyi
@@ -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: ...
+
diff --git a/frozen_deps/Cryptodome/Cipher/_mode_ccm.py b/frozen_deps/Cryptodome/Cipher/_mode_ccm.py
new file mode 100644
index 0000000..0e1c2f6
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_mode_ccm.py
@@ -0,0 +1,650 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# 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 = [self.update, self.encrypt, self.decrypt,
+ self.digest, self.verify]
+
+ # Cumulative lengths
+ self._cumul_assoc_len = 0
+ self._cumul_msg_len = 0
+
+ # Cache for unaligned associated data/plaintext.
+ # This is a list with byte strings, but when the MAC starts,
+ # it will become a binary string no longer than the block size.
+ self._cache = []
+
+ # Start CTR cipher, by formatting the counter (A.3)
+ q = 15 - len(nonce) # length of Q, the encoded message length
+ self._cipher = self._factory.new(key,
+ self._factory.MODE_CTR,
+ nonce=struct.pack("B", q - 1) + self.nonce,
+ **cipher_params)
+
+ # S_0, step 6 in 6.1 for j=0
+ self._s_0 = self._cipher.encrypt(b'\x00' * 16)
+
+ # Try to start the MAC
+ if None not in (assoc_len, msg_len):
+ self._start_mac()
+
+ def _start_mac(self):
+
+ assert(self._mac_status == MacStatus.NOT_STARTED)
+ assert(None not in (self._assoc_len, self._msg_len))
+ assert(isinstance(self._cache, list))
+
+ # Formatting control information and nonce (A.2.1)
+ q = 15 - len(self.nonce) # length of Q, the encoded message length
+ flags = (64 * (self._assoc_len > 0) + 8 * ((self._mac_len - 2) // 2) +
+ (q - 1))
+ b_0 = struct.pack("B", flags) + self.nonce + long_to_bytes(self._msg_len, q)
+
+ # Formatting associated data (A.2.2)
+ # Encoded 'a' is concatenated with the associated data 'A'
+ assoc_len_encoded = b''
+ if self._assoc_len > 0:
+ if self._assoc_len < (2 ** 16 - 2 ** 8):
+ enc_size = 2
+ elif self._assoc_len < (2 ** 32):
+ assoc_len_encoded = b'\xFF\xFE'
+ enc_size = 4
+ else:
+ assoc_len_encoded = b'\xFF\xFF'
+ enc_size = 8
+ assoc_len_encoded += long_to_bytes(self._assoc_len, enc_size)
+
+ # b_0 and assoc_len_encoded must be processed first
+ self._cache.insert(0, b_0)
+ self._cache.insert(1, assoc_len_encoded)
+
+ # Process all the data cached so far
+ first_data_to_mac = b"".join(self._cache)
+ self._cache = b""
+ self._mac_status = MacStatus.PROCESSING_AUTH_DATA
+ self._update(first_data_to_mac)
+
+ def _pad_cache_and_update(self):
+
+ assert(self._mac_status != MacStatus.NOT_STARTED)
+ assert(len(self._cache) < self.block_size)
+
+ # Associated data is concatenated with the least number
+ # of zero bytes (possibly none) to reach alignment to
+ # the 16 byte boundary (A.2.3)
+ len_cache = len(self._cache)
+ if len_cache > 0:
+ self._update(b'\x00' * (self.block_size - len_cache))
+
+ def update(self, assoc_data):
+ """Protect associated data
+
+ If there is any associated data, the caller has to invoke
+ this function one or more times, before using
+ ``decrypt`` or ``encrypt``.
+
+ By *associated data* it is meant any data (e.g. packet headers) that
+ will not be encrypted and will be transmitted in the clear.
+ However, the receiver is still able to detect any modification to it.
+ In CCM, the *associated data* is also called
+ *additional authenticated data* (AAD).
+
+ If there is no associated data, this method must not be called.
+
+ The caller may split associated data in segments of any size, and
+ invoke this method multiple times, each time with the next segment.
+
+ :Parameters:
+ assoc_data : bytes/bytearray/memoryview
+ A piece of associated data. There are no restrictions on its size.
+ """
+
+ if self.update not in self._next:
+ raise TypeError("update() can only be called"
+ " immediately after initialization")
+
+ self._next = [self.update, self.encrypt, self.decrypt,
+ self.digest, self.verify]
+
+ self._cumul_assoc_len += len(assoc_data)
+ if self._assoc_len is not None and \
+ self._cumul_assoc_len > self._assoc_len:
+ raise ValueError("Associated data is too long")
+
+ self._update(assoc_data)
+ return self
+
+ def _update(self, assoc_data_pt=b""):
+ """Update the MAC with associated data or plaintext
+ (without FSM checks)"""
+
+ # If MAC has not started yet, we just park the data into a list.
+ # If the data is mutable, we create a copy and store that instead.
+ if self._mac_status == MacStatus.NOT_STARTED:
+ if is_writeable_buffer(assoc_data_pt):
+ assoc_data_pt = _copy_bytes(None, None, assoc_data_pt)
+ self._cache.append(assoc_data_pt)
+ return
+
+ assert(len(self._cache) < self.block_size)
+
+ if len(self._cache) > 0:
+ filler = min(self.block_size - len(self._cache),
+ len(assoc_data_pt))
+ self._cache += _copy_bytes(None, filler, assoc_data_pt)
+ assoc_data_pt = _copy_bytes(filler, None, assoc_data_pt)
+
+ if len(self._cache) < self.block_size:
+ return
+
+ # The cache is exactly one block
+ self._t = self._mac.encrypt(self._cache)
+ self._cache = b""
+
+ update_len = len(assoc_data_pt) // self.block_size * self.block_size
+ self._cache = _copy_bytes(update_len, None, assoc_data_pt)
+ if update_len > 0:
+ self._t = self._mac.encrypt(assoc_data_pt[:update_len])[-16:]
+
+ def encrypt(self, plaintext, output=None):
+ """Encrypt data with the key set at initialization.
+
+ A cipher object is stateful: once you have encrypted a message
+ you cannot encrypt (or decrypt) another message using the same
+ object.
+
+ This method can be called only **once** if ``msg_len`` was
+ not passed at initialization.
+
+ If ``msg_len`` was given, the data to encrypt can be broken
+ up in two or more pieces and `encrypt` can be called
+ multiple times.
+
+ That is, the statement:
+
+ >>> c.encrypt(a) + c.encrypt(b)
+
+ is equivalent to:
+
+ >>> c.encrypt(a+b)
+
+ This function does not add any padding to the plaintext.
+
+ :Parameters:
+ plaintext : bytes/bytearray/memoryview
+ The piece of data to encrypt.
+ It can be of any length.
+ :Keywords:
+ output : bytearray/memoryview
+ The location where the ciphertext must be written to.
+ If ``None``, the ciphertext is returned.
+ :Return:
+ If ``output`` is ``None``, the ciphertext as ``bytes``.
+ Otherwise, ``None``.
+ """
+
+ if self.encrypt not in self._next:
+ raise TypeError("encrypt() can only be called after"
+ " initialization or an update()")
+ self._next = [self.encrypt, self.digest]
+
+ # No more associated data allowed from now
+ if self._assoc_len is None:
+ assert(isinstance(self._cache, list))
+ self._assoc_len = sum([len(x) for x in self._cache])
+ if self._msg_len is not None:
+ self._start_mac()
+ else:
+ if self._cumul_assoc_len < self._assoc_len:
+ raise ValueError("Associated data is too short")
+
+ # Only once piece of plaintext accepted if message length was
+ # not declared in advance
+ if self._msg_len is None:
+ self._msg_len = len(plaintext)
+ self._start_mac()
+ self._next = [self.digest]
+
+ self._cumul_msg_len += len(plaintext)
+ if self._cumul_msg_len > self._msg_len:
+ raise ValueError("Message is too long")
+
+ if self._mac_status == MacStatus.PROCESSING_AUTH_DATA:
+ # Associated data is concatenated with the least number
+ # of zero bytes (possibly none) to reach alignment to
+ # the 16 byte boundary (A.2.3)
+ self._pad_cache_and_update()
+ self._mac_status = MacStatus.PROCESSING_PLAINTEXT
+
+ self._update(plaintext)
+ return self._cipher.encrypt(plaintext, output=output)
+
+ def decrypt(self, ciphertext, output=None):
+ """Decrypt data with the key set at initialization.
+
+ A cipher object is stateful: once you have decrypted a message
+ you cannot decrypt (or encrypt) another message with the same
+ object.
+
+ This method can be called only **once** if ``msg_len`` was
+ not passed at initialization.
+
+ If ``msg_len`` was given, the data to decrypt can be
+ broken up in two or more pieces and `decrypt` can be
+ called multiple times.
+
+ That is, the statement:
+
+ >>> c.decrypt(a) + c.decrypt(b)
+
+ is equivalent to:
+
+ >>> c.decrypt(a+b)
+
+ This function does not remove any padding from the plaintext.
+
+ :Parameters:
+ ciphertext : bytes/bytearray/memoryview
+ The piece of data to decrypt.
+ It can be of any length.
+ :Keywords:
+ output : bytearray/memoryview
+ The location where the plaintext must be written to.
+ If ``None``, the plaintext is returned.
+ :Return:
+ If ``output`` is ``None``, the plaintext as ``bytes``.
+ Otherwise, ``None``.
+ """
+
+ if self.decrypt not in self._next:
+ raise TypeError("decrypt() can only be called"
+ " after initialization or an update()")
+ self._next = [self.decrypt, self.verify]
+
+ # No more associated data allowed from now
+ if self._assoc_len is None:
+ assert(isinstance(self._cache, list))
+ self._assoc_len = sum([len(x) for x in self._cache])
+ if self._msg_len is not None:
+ self._start_mac()
+ else:
+ if self._cumul_assoc_len < self._assoc_len:
+ raise ValueError("Associated data is too short")
+
+ # Only once piece of ciphertext accepted if message length was
+ # not declared in advance
+ if self._msg_len is None:
+ self._msg_len = len(ciphertext)
+ self._start_mac()
+ self._next = [self.verify]
+
+ self._cumul_msg_len += len(ciphertext)
+ if self._cumul_msg_len > self._msg_len:
+ raise ValueError("Message is too long")
+
+ if self._mac_status == MacStatus.PROCESSING_AUTH_DATA:
+ # Associated data is concatenated with the least number
+ # of zero bytes (possibly none) to reach alignment to
+ # the 16 byte boundary (A.2.3)
+ self._pad_cache_and_update()
+ self._mac_status = MacStatus.PROCESSING_PLAINTEXT
+
+ # Encrypt is equivalent to decrypt with the CTR mode
+ plaintext = self._cipher.encrypt(ciphertext, output=output)
+ if output is None:
+ self._update(plaintext)
+ else:
+ self._update(output)
+ return plaintext
+
+ def digest(self):
+ """Compute the *binary* MAC tag.
+
+ The caller invokes this function at the very end.
+
+ This method returns the MAC that shall be sent to the receiver,
+ together with the ciphertext.
+
+ :Return: the MAC, as a byte string.
+ """
+
+ if self.digest not in self._next:
+ raise TypeError("digest() cannot be called when decrypting"
+ " or validating a message")
+ self._next = [self.digest]
+ return self._digest()
+
+ def _digest(self):
+ if self._mac_tag:
+ return self._mac_tag
+
+ if self._assoc_len is None:
+ assert(isinstance(self._cache, list))
+ self._assoc_len = sum([len(x) for x in self._cache])
+ if self._msg_len is not None:
+ self._start_mac()
+ else:
+ if self._cumul_assoc_len < self._assoc_len:
+ raise ValueError("Associated data is too short")
+
+ if self._msg_len is None:
+ self._msg_len = 0
+ self._start_mac()
+
+ if self._cumul_msg_len != self._msg_len:
+ raise ValueError("Message is too short")
+
+ # Both associated data and payload are concatenated with the least
+ # number of zero bytes (possibly none) that align it to the
+ # 16 byte boundary (A.2.2 and A.2.3)
+ self._pad_cache_and_update()
+
+ # Step 8 in 6.1 (T xor MSB_Tlen(S_0))
+ self._mac_tag = strxor(self._t, self._s_0)[:self._mac_len]
+
+ return self._mac_tag
+
+ def hexdigest(self):
+ """Compute the *printable* MAC tag.
+
+ This method is like `digest`.
+
+ :Return: the MAC, as a hexadecimal string.
+ """
+ return "".join(["%02x" % bord(x) for x in self.digest()])
+
+ def verify(self, received_mac_tag):
+ """Validate the *binary* MAC tag.
+
+ The caller invokes this function at the very end.
+
+ This method checks if the decrypted message is indeed valid
+ (that is, if the key is correct) and it has not been
+ tampered with while in transit.
+
+ :Parameters:
+ received_mac_tag : bytes/bytearray/memoryview
+ This is the *binary* MAC, as received from the sender.
+ :Raises ValueError:
+ if the MAC does not match. The message has been tampered with
+ or the key is incorrect.
+ """
+
+ if self.verify not in self._next:
+ raise TypeError("verify() cannot be called"
+ " when encrypting a message")
+ self._next = [self.verify]
+
+ self._digest()
+ secret = get_random_bytes(16)
+
+ mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag)
+ mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag)
+
+ if mac1.digest() != mac2.digest():
+ raise ValueError("MAC check failed")
+
+ def hexverify(self, hex_mac_tag):
+ """Validate the *printable* MAC tag.
+
+ This method is like `verify`.
+
+ :Parameters:
+ hex_mac_tag : string
+ This is the *printable* MAC, as received from the sender.
+ :Raises ValueError:
+ if the MAC does not match. The message has been tampered with
+ or the key is incorrect.
+ """
+
+ self.verify(unhexlify(hex_mac_tag))
+
+ def encrypt_and_digest(self, plaintext, output=None):
+ """Perform encrypt() and digest() in one step.
+
+ :Parameters:
+ plaintext : bytes/bytearray/memoryview
+ The piece of data to encrypt.
+ :Keywords:
+ output : bytearray/memoryview
+ The location where the ciphertext must be written to.
+ If ``None``, the ciphertext is returned.
+ :Return:
+ a tuple with two items:
+
+ - the ciphertext, as ``bytes``
+ - the MAC tag, as ``bytes``
+
+ The first item becomes ``None`` when the ``output`` parameter
+ specified a location for the result.
+ """
+
+ return self.encrypt(plaintext, output=output), self.digest()
+
+ def decrypt_and_verify(self, ciphertext, received_mac_tag, output=None):
+ """Perform decrypt() and verify() in one step.
+
+ :Parameters:
+ ciphertext : bytes/bytearray/memoryview
+ The piece of data to decrypt.
+ received_mac_tag : bytes/bytearray/memoryview
+ This is the *binary* MAC, as received from the sender.
+ :Keywords:
+ output : bytearray/memoryview
+ The location where the plaintext must be written to.
+ If ``None``, the plaintext is returned.
+ :Return: the plaintext as ``bytes`` or ``None`` when the ``output``
+ parameter specified a location for the result.
+ :Raises ValueError:
+ if the MAC does not match. The message has been tampered with
+ or the key is incorrect.
+ """
+
+ plaintext = self.decrypt(ciphertext, output=output)
+ self.verify(received_mac_tag)
+ return plaintext
+
+
+def _create_ccm_cipher(factory, **kwargs):
+ """Create a new block cipher, configured in CCM mode.
+
+ :Parameters:
+ factory : module
+ A symmetric cipher module from `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)
diff --git a/frozen_deps/Cryptodome/Cipher/_mode_ccm.pyi b/frozen_deps/Cryptodome/Cipher/_mode_ccm.pyi
new file mode 100644
index 0000000..4b9f620
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_mode_ccm.pyi
@@ -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: ...
diff --git a/frozen_deps/Cryptodome/Cipher/_mode_cfb.py b/frozen_deps/Cryptodome/Cipher/_mode_cfb.py
new file mode 100644
index 0000000..b790dd4
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_mode_cfb.py
@@ -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 = [ self.encrypt, self.decrypt ]
+
+ def encrypt(self, plaintext, output=None):
+ """Encrypt data with the key and the parameters set at initialization.
+
+ A cipher object is stateful: once you have encrypted a message
+ you cannot encrypt (or decrypt) another message using the same
+ object.
+
+ The data to encrypt can be broken up in two or
+ more pieces and `encrypt` can be called multiple times.
+
+ That is, the statement:
+
+ >>> c.encrypt(a) + c.encrypt(b)
+
+ is equivalent to:
+
+ >>> c.encrypt(a+b)
+
+ This function does not add any padding to the plaintext.
+
+ :Parameters:
+ plaintext : bytes/bytearray/memoryview
+ The piece of data to encrypt.
+ It can be of any length.
+ :Keywords:
+ output : bytearray/memoryview
+ The location where the ciphertext must be written to.
+ If ``None``, the ciphertext is returned.
+ :Return:
+ If ``output`` is ``None``, the ciphertext is returned as ``bytes``.
+ Otherwise, ``None``.
+ """
+
+ if self.encrypt not in self._next:
+ raise TypeError("encrypt() cannot be called after decrypt()")
+ self._next = [ self.encrypt ]
+
+ if output is None:
+ ciphertext = create_string_buffer(len(plaintext))
+ else:
+ ciphertext = output
+
+ if not is_writeable_buffer(output):
+ raise TypeError("output must be a bytearray or a writeable memoryview")
+
+ if len(plaintext) != len(output):
+ raise ValueError("output must have the same length as the input"
+ " (%d bytes)" % len(plaintext))
+
+ result = raw_cfb_lib.CFB_encrypt(self._state.get(),
+ c_uint8_ptr(plaintext),
+ c_uint8_ptr(ciphertext),
+ c_size_t(len(plaintext)))
+ if result:
+ raise ValueError("Error %d while encrypting in CFB mode" % result)
+
+ if output is None:
+ return get_raw_buffer(ciphertext)
+ else:
+ return None
+
+ def decrypt(self, ciphertext, output=None):
+ """Decrypt data with the key and the parameters set at initialization.
+
+ A cipher object is stateful: once you have decrypted a message
+ you cannot decrypt (or encrypt) another message with the same
+ object.
+
+ The data to decrypt can be broken up in two or
+ more pieces and `decrypt` can be called multiple times.
+
+ That is, the statement:
+
+ >>> c.decrypt(a) + c.decrypt(b)
+
+ is equivalent to:
+
+ >>> c.decrypt(a+b)
+
+ This function does not remove any padding from the plaintext.
+
+ :Parameters:
+ ciphertext : bytes/bytearray/memoryview
+ The piece of data to decrypt.
+ It can be of any length.
+ :Keywords:
+ output : bytearray/memoryview
+ The location where the plaintext must be written to.
+ If ``None``, the plaintext is returned.
+ :Return:
+ If ``output`` is ``None``, the plaintext is returned as ``bytes``.
+ Otherwise, ``None``.
+ """
+
+ if self.decrypt not in self._next:
+ raise TypeError("decrypt() cannot be called after encrypt()")
+ self._next = [ self.decrypt ]
+
+ if output is None:
+ plaintext = create_string_buffer(len(ciphertext))
+ else:
+ plaintext = output
+
+ if not is_writeable_buffer(output):
+ raise TypeError("output must be a bytearray or a writeable memoryview")
+
+ if len(ciphertext) != len(output):
+ raise ValueError("output must have the same length as the input"
+ " (%d bytes)" % len(plaintext))
+
+ result = raw_cfb_lib.CFB_decrypt(self._state.get(),
+ c_uint8_ptr(ciphertext),
+ c_uint8_ptr(plaintext),
+ c_size_t(len(ciphertext)))
+ if result:
+ raise ValueError("Error %d while decrypting in CFB mode" % result)
+
+ if output is None:
+ return get_raw_buffer(plaintext)
+ else:
+ return None
+
+
+def _create_cfb_cipher(factory, **kwargs):
+ """Instantiate a cipher object that performs CFB encryption/decryption.
+
+ :Parameters:
+ factory : module
+ The underlying block cipher, a module from ``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)
diff --git a/frozen_deps/Cryptodome/Cipher/_mode_cfb.pyi b/frozen_deps/Cryptodome/Cipher/_mode_cfb.pyi
new file mode 100644
index 0000000..228e464
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_mode_cfb.pyi
@@ -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: ...
diff --git a/frozen_deps/Cryptodome/Cipher/_mode_ctr.py b/frozen_deps/Cryptodome/Cipher/_mode_ctr.py
new file mode 100644
index 0000000..99712d0
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_mode_ctr.py
@@ -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 = [self.encrypt, self.decrypt]
+
+ def encrypt(self, plaintext, output=None):
+ """Encrypt data with the key and the parameters set at initialization.
+
+ A cipher object is stateful: once you have encrypted a message
+ you cannot encrypt (or decrypt) another message using the same
+ object.
+
+ The data to encrypt can be broken up in two or
+ more pieces and `encrypt` can be called multiple times.
+
+ That is, the statement:
+
+ >>> c.encrypt(a) + c.encrypt(b)
+
+ is equivalent to:
+
+ >>> c.encrypt(a+b)
+
+ This function does not add any padding to the plaintext.
+
+ :Parameters:
+ plaintext : bytes/bytearray/memoryview
+ The piece of data to encrypt.
+ It can be of any length.
+ :Keywords:
+ output : bytearray/memoryview
+ The location where the ciphertext must be written to.
+ If ``None``, the ciphertext is returned.
+ :Return:
+ If ``output`` is ``None``, the ciphertext is returned as ``bytes``.
+ Otherwise, ``None``.
+ """
+
+ if self.encrypt not in self._next:
+ raise TypeError("encrypt() cannot be called after decrypt()")
+ self._next = [self.encrypt]
+
+ if output is None:
+ ciphertext = create_string_buffer(len(plaintext))
+ else:
+ ciphertext = output
+
+ if not is_writeable_buffer(output):
+ raise TypeError("output must be a bytearray or a writeable memoryview")
+
+ if len(plaintext) != len(output):
+ raise ValueError("output must have the same length as the input"
+ " (%d bytes)" % len(plaintext))
+
+ result = raw_ctr_lib.CTR_encrypt(self._state.get(),
+ c_uint8_ptr(plaintext),
+ c_uint8_ptr(ciphertext),
+ c_size_t(len(plaintext)))
+ if result:
+ if result == 0x60002:
+ raise OverflowError("The counter has wrapped around in"
+ " CTR mode")
+ raise ValueError("Error %X while encrypting in CTR mode" % result)
+
+ if output is None:
+ return get_raw_buffer(ciphertext)
+ else:
+ return None
+
+ def decrypt(self, ciphertext, output=None):
+ """Decrypt data with the key and the parameters set at initialization.
+
+ A cipher object is stateful: once you have decrypted a message
+ you cannot decrypt (or encrypt) another message with the same
+ object.
+
+ The data to decrypt can be broken up in two or
+ more pieces and `decrypt` can be called multiple times.
+
+ That is, the statement:
+
+ >>> c.decrypt(a) + c.decrypt(b)
+
+ is equivalent to:
+
+ >>> c.decrypt(a+b)
+
+ This function does not remove any padding from the plaintext.
+
+ :Parameters:
+ ciphertext : bytes/bytearray/memoryview
+ The piece of data to decrypt.
+ It can be of any length.
+ :Keywords:
+ output : bytearray/memoryview
+ The location where the plaintext must be written to.
+ If ``None``, the plaintext is returned.
+ :Return:
+ If ``output`` is ``None``, the plaintext is returned as ``bytes``.
+ Otherwise, ``None``.
+ """
+
+ if self.decrypt not in self._next:
+ raise TypeError("decrypt() cannot be called after encrypt()")
+ self._next = [self.decrypt]
+
+ if output is None:
+ plaintext = create_string_buffer(len(ciphertext))
+ else:
+ plaintext = output
+
+ if not is_writeable_buffer(output):
+ raise TypeError("output must be a bytearray or a writeable memoryview")
+
+ if len(ciphertext) != len(output):
+ raise ValueError("output must have the same length as the input"
+ " (%d bytes)" % len(plaintext))
+
+
+ result = raw_ctr_lib.CTR_decrypt(self._state.get(),
+ c_uint8_ptr(ciphertext),
+ c_uint8_ptr(plaintext),
+ c_size_t(len(ciphertext)))
+ if result:
+ if result == 0x60002:
+ raise OverflowError("The counter has wrapped around in"
+ " CTR mode")
+ raise ValueError("Error %X while decrypting in CTR mode" % result)
+
+ if output is None:
+ return get_raw_buffer(plaintext)
+ else:
+ return None
+
+
+def _create_ctr_cipher(factory, **kwargs):
+ """Instantiate a cipher object that performs CTR encryption/decryption.
+
+ :Parameters:
+ factory : module
+ The underlying block cipher, a module from ``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)
diff --git a/frozen_deps/Cryptodome/Cipher/_mode_ctr.pyi b/frozen_deps/Cryptodome/Cipher/_mode_ctr.pyi
new file mode 100644
index 0000000..a68a890
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_mode_ctr.pyi
@@ -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: ...
+
diff --git a/frozen_deps/Cryptodome/Cipher/_mode_eax.py b/frozen_deps/Cryptodome/Cipher/_mode_eax.py
new file mode 100644
index 0000000..8efb77a
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_mode_eax.py
@@ -0,0 +1,408 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# 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 = [self.update, self.encrypt, self.decrypt,
+ self.digest, self.verify]
+
+ # MAC tag length
+ if not (4 <= self._mac_len <= self.block_size):
+ raise ValueError("Parameter 'mac_len' must not be larger than %d"
+ % self.block_size)
+
+ # Nonce cannot be empty and must be a byte string
+ if len(self.nonce) == 0:
+ raise ValueError("Nonce cannot be empty in EAX mode")
+ if not is_buffer(nonce):
+ raise TypeError("nonce must be bytes, bytearray or memoryview")
+
+ self._omac = [
+ CMAC.new(key,
+ b'\x00' * (self.block_size - 1) + struct.pack('B', i),
+ ciphermod=factory,
+ cipher_params=cipher_params)
+ for i in range(0, 3)
+ ]
+
+ # Compute MAC of nonce
+ self._omac[0].update(self.nonce)
+ self._signer = self._omac[1]
+
+ # MAC of the nonce is also the initial counter for CTR encryption
+ counter_int = bytes_to_long(self._omac[0].digest())
+ self._cipher = factory.new(key,
+ factory.MODE_CTR,
+ initial_value=counter_int,
+ nonce=b"",
+ **cipher_params)
+
+ def update(self, assoc_data):
+ """Protect associated data
+
+ If there is any associated data, the caller has to invoke
+ this function one or more times, before using
+ ``decrypt`` or ``encrypt``.
+
+ By *associated data* it is meant any data (e.g. packet headers) that
+ will not be encrypted and will be transmitted in the clear.
+ However, the receiver is still able to detect any modification to it.
+
+ If there is no associated data, this method must not be called.
+
+ The caller may split associated data in segments of any size, and
+ invoke this method multiple times, each time with the next segment.
+
+ :Parameters:
+ assoc_data : bytes/bytearray/memoryview
+ A piece of associated data. There are no restrictions on its size.
+ """
+
+ if self.update not in self._next:
+ raise TypeError("update() can only be called"
+ " immediately after initialization")
+
+ self._next = [self.update, self.encrypt, self.decrypt,
+ self.digest, self.verify]
+
+ self._signer.update(assoc_data)
+ return self
+
+ def encrypt(self, plaintext, output=None):
+ """Encrypt data with the key and the parameters set at initialization.
+
+ A cipher object is stateful: once you have encrypted a message
+ you cannot encrypt (or decrypt) another message using the same
+ object.
+
+ The data to encrypt can be broken up in two or
+ more pieces and `encrypt` can be called multiple times.
+
+ That is, the statement:
+
+ >>> c.encrypt(a) + c.encrypt(b)
+
+ is equivalent to:
+
+ >>> c.encrypt(a+b)
+
+ This function does not add any padding to the plaintext.
+
+ :Parameters:
+ plaintext : bytes/bytearray/memoryview
+ The piece of data to encrypt.
+ It can be of any length.
+ :Keywords:
+ output : bytearray/memoryview
+ The location where the ciphertext must be written to.
+ If ``None``, the ciphertext is returned.
+ :Return:
+ If ``output`` is ``None``, the ciphertext as ``bytes``.
+ Otherwise, ``None``.
+ """
+
+ if self.encrypt not in self._next:
+ raise TypeError("encrypt() can only be called after"
+ " initialization or an update()")
+ self._next = [self.encrypt, self.digest]
+ ct = self._cipher.encrypt(plaintext, output=output)
+ if output is None:
+ self._omac[2].update(ct)
+ else:
+ self._omac[2].update(output)
+ return ct
+
+ def decrypt(self, ciphertext, output=None):
+ """Decrypt data with the key and the parameters set at initialization.
+
+ A cipher object is stateful: once you have decrypted a message
+ you cannot decrypt (or encrypt) another message with the same
+ object.
+
+ The data to decrypt can be broken up in two or
+ more pieces and `decrypt` can be called multiple times.
+
+ That is, the statement:
+
+ >>> c.decrypt(a) + c.decrypt(b)
+
+ is equivalent to:
+
+ >>> c.decrypt(a+b)
+
+ This function does not remove any padding from the plaintext.
+
+ :Parameters:
+ ciphertext : bytes/bytearray/memoryview
+ The piece of data to decrypt.
+ It can be of any length.
+ :Keywords:
+ output : bytearray/memoryview
+ The location where the plaintext must be written to.
+ If ``None``, the plaintext is returned.
+ :Return:
+ If ``output`` is ``None``, the plaintext as ``bytes``.
+ Otherwise, ``None``.
+ """
+
+ if self.decrypt not in self._next:
+ raise TypeError("decrypt() can only be called"
+ " after initialization or an update()")
+ self._next = [self.decrypt, self.verify]
+ self._omac[2].update(ciphertext)
+ return self._cipher.decrypt(ciphertext, output=output)
+
+ def digest(self):
+ """Compute the *binary* MAC tag.
+
+ The caller invokes this function at the very end.
+
+ This method returns the MAC that shall be sent to the receiver,
+ together with the ciphertext.
+
+ :Return: the MAC, as a byte string.
+ """
+
+ if self.digest not in self._next:
+ raise TypeError("digest() cannot be called when decrypting"
+ " or validating a message")
+ self._next = [self.digest]
+
+ if not self._mac_tag:
+ tag = b'\x00' * self.block_size
+ for i in range(3):
+ tag = strxor(tag, self._omac[i].digest())
+ self._mac_tag = tag[:self._mac_len]
+
+ return self._mac_tag
+
+ def hexdigest(self):
+ """Compute the *printable* MAC tag.
+
+ This method is like `digest`.
+
+ :Return: the MAC, as a hexadecimal string.
+ """
+ return "".join(["%02x" % bord(x) for x in self.digest()])
+
+ def verify(self, received_mac_tag):
+ """Validate the *binary* MAC tag.
+
+ The caller invokes this function at the very end.
+
+ This method checks if the decrypted message is indeed valid
+ (that is, if the key is correct) and it has not been
+ tampered with while in transit.
+
+ :Parameters:
+ received_mac_tag : bytes/bytearray/memoryview
+ This is the *binary* MAC, as received from the sender.
+ :Raises MacMismatchError:
+ if the MAC does not match. The message has been tampered with
+ or the key is incorrect.
+ """
+
+ if self.verify not in self._next:
+ raise TypeError("verify() cannot be called"
+ " when encrypting a message")
+ self._next = [self.verify]
+
+ if not self._mac_tag:
+ tag = b'\x00' * self.block_size
+ for i in range(3):
+ tag = strxor(tag, self._omac[i].digest())
+ self._mac_tag = tag[:self._mac_len]
+
+ secret = get_random_bytes(16)
+
+ mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag)
+ mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag)
+
+ if mac1.digest() != mac2.digest():
+ raise ValueError("MAC check failed")
+
+ def hexverify(self, hex_mac_tag):
+ """Validate the *printable* MAC tag.
+
+ This method is like `verify`.
+
+ :Parameters:
+ hex_mac_tag : string
+ This is the *printable* MAC, as received from the sender.
+ :Raises MacMismatchError:
+ if the MAC does not match. The message has been tampered with
+ or the key is incorrect.
+ """
+
+ self.verify(unhexlify(hex_mac_tag))
+
+ def encrypt_and_digest(self, plaintext, output=None):
+ """Perform encrypt() and digest() in one step.
+
+ :Parameters:
+ plaintext : bytes/bytearray/memoryview
+ The piece of data to encrypt.
+ :Keywords:
+ output : bytearray/memoryview
+ The location where the ciphertext must be written to.
+ If ``None``, the ciphertext is returned.
+ :Return:
+ a tuple with two items:
+
+ - the ciphertext, as ``bytes``
+ - the MAC tag, as ``bytes``
+
+ The first item becomes ``None`` when the ``output`` parameter
+ specified a location for the result.
+ """
+
+ return self.encrypt(plaintext, output=output), self.digest()
+
+ def decrypt_and_verify(self, ciphertext, received_mac_tag, output=None):
+ """Perform decrypt() and verify() in one step.
+
+ :Parameters:
+ ciphertext : bytes/bytearray/memoryview
+ The piece of data to decrypt.
+ received_mac_tag : bytes/bytearray/memoryview
+ This is the *binary* MAC, as received from the sender.
+ :Keywords:
+ output : bytearray/memoryview
+ The location where the plaintext must be written to.
+ If ``None``, the plaintext is returned.
+ :Return: the plaintext as ``bytes`` or ``None`` when the ``output``
+ parameter specified a location for the result.
+ :Raises MacMismatchError:
+ if the MAC does not match. The message has been tampered with
+ or the key is incorrect.
+ """
+
+ pt = self.decrypt(ciphertext, output=output)
+ self.verify(received_mac_tag)
+ return pt
+
+
+def _create_eax_cipher(factory, **kwargs):
+ """Create a new block cipher, configured in EAX mode.
+
+ :Parameters:
+ factory : module
+ A symmetric cipher module from `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)
diff --git a/frozen_deps/Cryptodome/Cipher/_mode_eax.pyi b/frozen_deps/Cryptodome/Cipher/_mode_eax.pyi
new file mode 100644
index 0000000..cbfa467
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_mode_eax.pyi
@@ -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: ...
diff --git a/frozen_deps/Cryptodome/Cipher/_mode_ecb.py b/frozen_deps/Cryptodome/Cipher/_mode_ecb.py
new file mode 100644
index 0000000..4c381f7
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_mode_ecb.py
@@ -0,0 +1,218 @@
+# -*- 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._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)
+ if kwargs:
+ raise TypeError("Unknown parameters for ECB: %s" % str(kwargs))
+ return EcbMode(cipher_state)
diff --git a/frozen_deps/Cryptodome/Cipher/_mode_ecb.pyi b/frozen_deps/Cryptodome/Cipher/_mode_ecb.pyi
new file mode 100644
index 0000000..936195f
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_mode_ecb.pyi
@@ -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: ...
+
diff --git a/frozen_deps/Cryptodome/Cipher/_mode_gcm.py b/frozen_deps/Cryptodome/Cipher/_mode_gcm.py
new file mode 100644
index 0000000..c90061b
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_mode_gcm.py
@@ -0,0 +1,620 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# 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 = [self.update, self.encrypt, self.decrypt,
+ self.digest, self.verify]
+
+ self._no_more_assoc_data = False
+
+ # Length of associated data
+ self._auth_len = 0
+
+ # Length of the ciphertext or plaintext
+ self._msg_len = 0
+
+ # Step 1 in SP800-38D, Algorithm 4 (encryption) - Compute H
+ # See also Algorithm 5 (decryption)
+ hash_subkey = factory.new(key,
+ self._factory.MODE_ECB,
+ **cipher_params
+ ).encrypt(b'\x00' * 16)
+
+ # Step 2 - Compute J0
+ if len(self.nonce) == 12:
+ j0 = self.nonce + b"\x00\x00\x00\x01"
+ else:
+ fill = (16 - (len(nonce) % 16)) % 16 + 8
+ ghash_in = (self.nonce +
+ b'\x00' * fill +
+ long_to_bytes(8 * len(nonce), 8))
+ j0 = _GHASH(hash_subkey, ghash_c).update(ghash_in).digest()
+
+ # Step 3 - Prepare GCTR cipher for encryption/decryption
+ nonce_ctr = j0[:12]
+ iv_ctr = (bytes_to_long(j0) + 1) & 0xFFFFFFFF
+ self._cipher = factory.new(key,
+ self._factory.MODE_CTR,
+ initial_value=iv_ctr,
+ nonce=nonce_ctr,
+ **cipher_params)
+
+ # Step 5 - Bootstrat GHASH
+ self._signer = _GHASH(hash_subkey, ghash_c)
+
+ # Step 6 - Prepare GCTR cipher for GMAC
+ self._tag_cipher = factory.new(key,
+ self._factory.MODE_CTR,
+ initial_value=j0,
+ nonce=b"",
+ **cipher_params)
+
+ # Cache for data to authenticate
+ self._cache = b""
+
+ self._status = MacStatus.PROCESSING_AUTH_DATA
+
+ def update(self, assoc_data):
+ """Protect associated data
+
+ If there is any associated data, the caller has to invoke
+ this function one or more times, before using
+ ``decrypt`` or ``encrypt``.
+
+ By *associated data* it is meant any data (e.g. packet headers) that
+ will not be encrypted and will be transmitted in the clear.
+ However, the receiver is still able to detect any modification to it.
+ In GCM, the *associated data* is also called
+ *additional authenticated data* (AAD).
+
+ If there is no associated data, this method must not be called.
+
+ The caller may split associated data in segments of any size, and
+ invoke this method multiple times, each time with the next segment.
+
+ :Parameters:
+ assoc_data : bytes/bytearray/memoryview
+ A piece of associated data. There are no restrictions on its size.
+ """
+
+ if self.update not in self._next:
+ raise TypeError("update() can only be called"
+ " immediately after initialization")
+
+ self._next = [self.update, self.encrypt, self.decrypt,
+ self.digest, self.verify]
+
+ self._update(assoc_data)
+ self._auth_len += len(assoc_data)
+
+ # See NIST SP 800 38D, 5.2.1.1
+ if self._auth_len > 2**64 - 1:
+ raise ValueError("Additional Authenticated Data exceeds maximum length")
+
+ return self
+
+ def _update(self, data):
+ assert(len(self._cache) < 16)
+
+ if len(self._cache) > 0:
+ filler = min(16 - len(self._cache), len(data))
+ self._cache += _copy_bytes(None, filler, data)
+ data = data[filler:]
+
+ if len(self._cache) < 16:
+ return
+
+ # The cache is exactly one block
+ self._signer.update(self._cache)
+ self._cache = b""
+
+ update_len = len(data) // 16 * 16
+ self._cache = _copy_bytes(update_len, None, data)
+ if update_len > 0:
+ self._signer.update(data[:update_len])
+
+ def _pad_cache_and_update(self):
+ assert(len(self._cache) < 16)
+
+ # The authenticated data A is concatenated to the minimum
+ # number of zero bytes (possibly none) such that the
+ # - ciphertext C is aligned to the 16 byte boundary.
+ # See step 5 in section 7.1
+ # - ciphertext C is aligned to the 16 byte boundary.
+ # See step 6 in section 7.2
+ len_cache = len(self._cache)
+ if len_cache > 0:
+ self._update(b'\x00' * (16 - len_cache))
+
+ def encrypt(self, plaintext, output=None):
+ """Encrypt data with the key and the parameters set at initialization.
+
+ A cipher object is stateful: once you have encrypted a message
+ you cannot encrypt (or decrypt) another message using the same
+ object.
+
+ The data to encrypt can be broken up in two or
+ more pieces and `encrypt` can be called multiple times.
+
+ That is, the statement:
+
+ >>> c.encrypt(a) + c.encrypt(b)
+
+ is equivalent to:
+
+ >>> c.encrypt(a+b)
+
+ This function does not add any padding to the plaintext.
+
+ :Parameters:
+ plaintext : bytes/bytearray/memoryview
+ The piece of data to encrypt.
+ It can be of any length.
+ :Keywords:
+ output : bytearray/memoryview
+ The location where the ciphertext must be written to.
+ If ``None``, the ciphertext is returned.
+ :Return:
+ If ``output`` is ``None``, the ciphertext as ``bytes``.
+ Otherwise, ``None``.
+ """
+
+ if self.encrypt not in self._next:
+ raise TypeError("encrypt() can only be called after"
+ " initialization or an update()")
+ self._next = [self.encrypt, self.digest]
+
+ ciphertext = self._cipher.encrypt(plaintext, output=output)
+
+ if self._status == MacStatus.PROCESSING_AUTH_DATA:
+ self._pad_cache_and_update()
+ self._status = MacStatus.PROCESSING_CIPHERTEXT
+
+ self._update(ciphertext if output is None else output)
+ self._msg_len += len(plaintext)
+
+ # See NIST SP 800 38D, 5.2.1.1
+ if self._msg_len > 2**39 - 256:
+ raise ValueError("Plaintext exceeds maximum length")
+
+ return ciphertext
+
+ def decrypt(self, ciphertext, output=None):
+ """Decrypt data with the key and the parameters set at initialization.
+
+ A cipher object is stateful: once you have decrypted a message
+ you cannot decrypt (or encrypt) another message with the same
+ object.
+
+ The data to decrypt can be broken up in two or
+ more pieces and `decrypt` can be called multiple times.
+
+ That is, the statement:
+
+ >>> c.decrypt(a) + c.decrypt(b)
+
+ is equivalent to:
+
+ >>> c.decrypt(a+b)
+
+ This function does not remove any padding from the plaintext.
+
+ :Parameters:
+ ciphertext : bytes/bytearray/memoryview
+ The piece of data to decrypt.
+ It can be of any length.
+ :Keywords:
+ output : bytearray/memoryview
+ The location where the plaintext must be written to.
+ If ``None``, the plaintext is returned.
+ :Return:
+ If ``output`` is ``None``, the plaintext as ``bytes``.
+ Otherwise, ``None``.
+ """
+
+ if self.decrypt not in self._next:
+ raise TypeError("decrypt() can only be called"
+ " after initialization or an update()")
+ self._next = [self.decrypt, self.verify]
+
+ if self._status == MacStatus.PROCESSING_AUTH_DATA:
+ self._pad_cache_and_update()
+ self._status = MacStatus.PROCESSING_CIPHERTEXT
+
+ self._update(ciphertext)
+ self._msg_len += len(ciphertext)
+
+ return self._cipher.decrypt(ciphertext, output=output)
+
+ def digest(self):
+ """Compute the *binary* MAC tag in an AEAD mode.
+
+ The caller invokes this function at the very end.
+
+ This method returns the MAC that shall be sent to the receiver,
+ together with the ciphertext.
+
+ :Return: the MAC, as a byte string.
+ """
+
+ if self.digest not in self._next:
+ raise TypeError("digest() cannot be called when decrypting"
+ " or validating a message")
+ self._next = [self.digest]
+
+ return self._compute_mac()
+
+ def _compute_mac(self):
+ """Compute MAC without any FSM checks."""
+
+ if self._tag:
+ return self._tag
+
+ # Step 5 in NIST SP 800-38D, Algorithm 4 - Compute S
+ self._pad_cache_and_update()
+ self._update(long_to_bytes(8 * self._auth_len, 8))
+ self._update(long_to_bytes(8 * self._msg_len, 8))
+ s_tag = self._signer.digest()
+
+ # Step 6 - Compute T
+ self._tag = self._tag_cipher.encrypt(s_tag)[:self._mac_len]
+
+ return self._tag
+
+ def hexdigest(self):
+ """Compute the *printable* MAC tag.
+
+ This method is like `digest`.
+
+ :Return: the MAC, as a hexadecimal string.
+ """
+ return "".join(["%02x" % bord(x) for x in self.digest()])
+
+ def verify(self, received_mac_tag):
+ """Validate the *binary* MAC tag.
+
+ The caller invokes this function at the very end.
+
+ This method checks if the decrypted message is indeed valid
+ (that is, if the key is correct) and it has not been
+ tampered with while in transit.
+
+ :Parameters:
+ received_mac_tag : bytes/bytearray/memoryview
+ This is the *binary* MAC, as received from the sender.
+ :Raises ValueError:
+ if the MAC does not match. The message has been tampered with
+ or the key is incorrect.
+ """
+
+ if self.verify not in self._next:
+ raise TypeError("verify() cannot be called"
+ " when encrypting a message")
+ self._next = [self.verify]
+
+ secret = get_random_bytes(16)
+
+ mac1 = BLAKE2s.new(digest_bits=160, key=secret,
+ data=self._compute_mac())
+ mac2 = BLAKE2s.new(digest_bits=160, key=secret,
+ data=received_mac_tag)
+
+ if mac1.digest() != mac2.digest():
+ raise ValueError("MAC check failed")
+
+ def hexverify(self, hex_mac_tag):
+ """Validate the *printable* MAC tag.
+
+ This method is like `verify`.
+
+ :Parameters:
+ hex_mac_tag : string
+ This is the *printable* MAC, as received from the sender.
+ :Raises ValueError:
+ if the MAC does not match. The message has been tampered with
+ or the key is incorrect.
+ """
+
+ self.verify(unhexlify(hex_mac_tag))
+
+ def encrypt_and_digest(self, plaintext, output=None):
+ """Perform encrypt() and digest() in one step.
+
+ :Parameters:
+ plaintext : bytes/bytearray/memoryview
+ The piece of data to encrypt.
+ :Keywords:
+ output : bytearray/memoryview
+ The location where the ciphertext must be written to.
+ If ``None``, the ciphertext is returned.
+ :Return:
+ a tuple with two items:
+
+ - the ciphertext, as ``bytes``
+ - the MAC tag, as ``bytes``
+
+ The first item becomes ``None`` when the ``output`` parameter
+ specified a location for the result.
+ """
+
+ return self.encrypt(plaintext, output=output), self.digest()
+
+ def decrypt_and_verify(self, ciphertext, received_mac_tag, output=None):
+ """Perform decrypt() and verify() in one step.
+
+ :Parameters:
+ ciphertext : bytes/bytearray/memoryview
+ The piece of data to decrypt.
+ received_mac_tag : byte string
+ This is the *binary* MAC, as received from the sender.
+ :Keywords:
+ output : bytearray/memoryview
+ The location where the plaintext must be written to.
+ If ``None``, the plaintext is returned.
+ :Return: the plaintext as ``bytes`` or ``None`` when the ``output``
+ parameter specified a location for the result.
+ :Raises ValueError:
+ if the MAC does not match. The message has been tampered with
+ or the key is incorrect.
+ """
+
+ plaintext = self.decrypt(ciphertext, output=output)
+ self.verify(received_mac_tag)
+ return plaintext
+
+
+def _create_gcm_cipher(factory, **kwargs):
+ """Create a new block cipher, configured in Galois Counter Mode (GCM).
+
+ :Parameters:
+ factory : module
+ A block cipher module, taken from `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)
diff --git a/frozen_deps/Cryptodome/Cipher/_mode_gcm.pyi b/frozen_deps/Cryptodome/Cipher/_mode_gcm.pyi
new file mode 100644
index 0000000..8912955
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_mode_gcm.pyi
@@ -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: ...
diff --git a/frozen_deps/Cryptodome/Cipher/_mode_ocb.py b/frozen_deps/Cryptodome/Cipher/_mode_ocb.py
new file mode 100644
index 0000000..27c2797
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_mode_ocb.py
@@ -0,0 +1,525 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# 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
+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 = [self.update, self.encrypt, self.decrypt,
+ self.digest, self.verify]
+
+ # Compute Offset_0
+ params_without_key = dict(cipher_params)
+ key = params_without_key.pop("key")
+ nonce = (struct.pack('B', self._mac_len << 4 & 0xFF) +
+ b'\x00' * (14 - len(nonce)) +
+ b'\x01' + self.nonce)
+
+ bottom_bits = bord(nonce[15]) & 0x3F # 6 bits, 0..63
+ top_bits = bord(nonce[15]) & 0xC0 # 2 bits
+
+ ktop_cipher = factory.new(key,
+ factory.MODE_ECB,
+ **params_without_key)
+ ktop = ktop_cipher.encrypt(struct.pack('15sB',
+ nonce[:15],
+ top_bits))
+
+ stretch = ktop + strxor(ktop[:8], ktop[1:9]) # 192 bits
+ offset_0 = long_to_bytes(bytes_to_long(stretch) >>
+ (64 - bottom_bits), 24)[8:]
+
+ # Create low-level cipher instance
+ raw_cipher = factory._create_base_cipher(cipher_params)
+ if cipher_params:
+ raise TypeError("Unknown keywords: " + str(cipher_params))
+
+ self._state = VoidPointer()
+ result = _raw_ocb_lib.OCB_start_operation(raw_cipher.get(),
+ offset_0,
+ c_size_t(len(offset_0)),
+ self._state.address_of())
+ if result:
+ raise ValueError("Error %d while instantiating the OCB mode"
+ % result)
+
+ # Ensure that object disposal of this Python object will (eventually)
+ # free the memory allocated by the raw library for the cipher mode
+ self._state = SmartPointer(self._state.get(),
+ _raw_ocb_lib.OCB_stop_operation)
+
+ # Memory allocated for the underlying block cipher is now owed
+ # by the cipher mode
+ raw_cipher.release()
+
+ def _update(self, assoc_data, assoc_data_len):
+ result = _raw_ocb_lib.OCB_update(self._state.get(),
+ c_uint8_ptr(assoc_data),
+ c_size_t(assoc_data_len))
+ if result:
+ raise ValueError("Error %d while computing MAC in OCB mode" % result)
+
+ def update(self, assoc_data):
+ """Process the associated data.
+
+ If there is any associated data, the caller has to invoke
+ this method one or more times, before using
+ ``decrypt`` or ``encrypt``.
+
+ By *associated data* it is meant any data (e.g. packet headers) that
+ will not be encrypted and will be transmitted in the clear.
+ However, the receiver shall still able to detect modifications.
+
+ If there is no associated data, this method must not be called.
+
+ The caller may split associated data in segments of any size, and
+ invoke this method multiple times, each time with the next segment.
+
+ :Parameters:
+ assoc_data : bytes/bytearray/memoryview
+ A piece of associated data.
+ """
+
+ if self.update not in self._next:
+ raise TypeError("update() can only be called"
+ " immediately after initialization")
+
+ self._next = [self.encrypt, self.decrypt, self.digest,
+ self.verify, self.update]
+
+ if len(self._cache_A) > 0:
+ filler = min(16 - len(self._cache_A), len(assoc_data))
+ self._cache_A += _copy_bytes(None, filler, assoc_data)
+ assoc_data = assoc_data[filler:]
+
+ if len(self._cache_A) < 16:
+ return self
+
+ # Clear the cache, and proceeding with any other aligned data
+ self._cache_A, seg = b"", self._cache_A
+ self.update(seg)
+
+ update_len = len(assoc_data) // 16 * 16
+ self._cache_A = _copy_bytes(update_len, None, assoc_data)
+ self._update(assoc_data, update_len)
+ return self
+
+ def _transcrypt_aligned(self, in_data, in_data_len,
+ trans_func, trans_desc):
+
+ out_data = create_string_buffer(in_data_len)
+ result = trans_func(self._state.get(),
+ in_data,
+ out_data,
+ c_size_t(in_data_len))
+ if result:
+ raise ValueError("Error %d while %sing in OCB mode"
+ % (result, trans_desc))
+ return get_raw_buffer(out_data)
+
+ def _transcrypt(self, in_data, trans_func, trans_desc):
+ # Last piece to encrypt/decrypt
+ if in_data is None:
+ out_data = self._transcrypt_aligned(self._cache_P,
+ len(self._cache_P),
+ trans_func,
+ trans_desc)
+ self._cache_P = b""
+ return out_data
+
+ # Try to fill up the cache, if it already contains something
+ prefix = b""
+ if len(self._cache_P) > 0:
+ filler = min(16 - len(self._cache_P), len(in_data))
+ self._cache_P += _copy_bytes(None, filler, in_data)
+ in_data = in_data[filler:]
+
+ if len(self._cache_P) < 16:
+ # We could not manage to fill the cache, so there is certainly
+ # no output yet.
+ return b""
+
+ # Clear the cache, and proceeding with any other aligned data
+ prefix = self._transcrypt_aligned(self._cache_P,
+ len(self._cache_P),
+ trans_func,
+ trans_desc)
+ self._cache_P = b""
+
+ # Process data in multiples of the block size
+ trans_len = len(in_data) // 16 * 16
+ result = self._transcrypt_aligned(c_uint8_ptr(in_data),
+ trans_len,
+ trans_func,
+ trans_desc)
+ if prefix:
+ result = prefix + result
+
+ # Left-over
+ self._cache_P = _copy_bytes(trans_len, None, in_data)
+
+ return result
+
+ def encrypt(self, plaintext=None):
+ """Encrypt the next piece of plaintext.
+
+ After the entire plaintext has been passed (but before `digest`),
+ you **must** call this method one last time with no arguments to collect
+ the final piece of ciphertext.
+
+ If possible, use the method `encrypt_and_digest` instead.
+
+ :Parameters:
+ plaintext : bytes/bytearray/memoryview
+ The next piece of data to encrypt or ``None`` to signify
+ that encryption has finished and that any remaining ciphertext
+ has to be produced.
+ :Return:
+ the ciphertext, as a byte string.
+ Its length may not match the length of the *plaintext*.
+ """
+
+ if self.encrypt not in self._next:
+ raise TypeError("encrypt() can only be called after"
+ " initialization or an update()")
+
+ if plaintext is None:
+ self._next = [self.digest]
+ else:
+ self._next = [self.encrypt]
+ return self._transcrypt(plaintext, _raw_ocb_lib.OCB_encrypt, "encrypt")
+
+ def decrypt(self, ciphertext=None):
+ """Decrypt the next piece of ciphertext.
+
+ After the entire ciphertext has been passed (but before `verify`),
+ you **must** call this method one last time with no arguments to collect
+ the remaining piece of plaintext.
+
+ If possible, use the method `decrypt_and_verify` instead.
+
+ :Parameters:
+ ciphertext : bytes/bytearray/memoryview
+ The next piece of data to decrypt or ``None`` to signify
+ that decryption has finished and that any remaining plaintext
+ has to be produced.
+ :Return:
+ the plaintext, as a byte string.
+ Its length may not match the length of the *ciphertext*.
+ """
+
+ if self.decrypt not in self._next:
+ raise TypeError("decrypt() can only be called after"
+ " initialization or an update()")
+
+ if ciphertext is None:
+ self._next = [self.verify]
+ else:
+ self._next = [self.decrypt]
+ return self._transcrypt(ciphertext,
+ _raw_ocb_lib.OCB_decrypt,
+ "decrypt")
+
+ def _compute_mac_tag(self):
+
+ if self._mac_tag is not None:
+ return
+
+ if self._cache_A:
+ self._update(self._cache_A, len(self._cache_A))
+ self._cache_A = b""
+
+ mac_tag = create_string_buffer(16)
+ result = _raw_ocb_lib.OCB_digest(self._state.get(),
+ mac_tag,
+ c_size_t(len(mac_tag))
+ )
+ if result:
+ raise ValueError("Error %d while computing digest in OCB mode"
+ % result)
+ self._mac_tag = get_raw_buffer(mac_tag)[:self._mac_len]
+
+ def digest(self):
+ """Compute the *binary* MAC tag.
+
+ Call this method after the final `encrypt` (the one with no arguments)
+ to obtain the MAC tag.
+
+ The MAC tag is needed by the receiver to determine authenticity
+ of the message.
+
+ :Return: the MAC, as a byte string.
+ """
+
+ if self.digest not in self._next:
+ raise TypeError("digest() cannot be called now for this cipher")
+
+ assert(len(self._cache_P) == 0)
+
+ self._next = [self.digest]
+
+ if self._mac_tag is None:
+ self._compute_mac_tag()
+
+ return self._mac_tag
+
+ def hexdigest(self):
+ """Compute the *printable* MAC tag.
+
+ This method is like `digest`.
+
+ :Return: the MAC, as a hexadecimal string.
+ """
+ return "".join(["%02x" % bord(x) for x in self.digest()])
+
+ def verify(self, received_mac_tag):
+ """Validate the *binary* MAC tag.
+
+ Call this method after the final `decrypt` (the one with no arguments)
+ to check if the message is authentic and valid.
+
+ :Parameters:
+ received_mac_tag : bytes/bytearray/memoryview
+ This is the *binary* MAC, as received from the sender.
+ :Raises ValueError:
+ if the MAC does not match. The message has been tampered with
+ or the key is incorrect.
+ """
+
+ if self.verify not in self._next:
+ raise TypeError("verify() cannot be called now for this cipher")
+
+ assert(len(self._cache_P) == 0)
+
+ self._next = [self.verify]
+
+ if self._mac_tag is None:
+ self._compute_mac_tag()
+
+ secret = get_random_bytes(16)
+ mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag)
+ mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag)
+
+ if mac1.digest() != mac2.digest():
+ raise ValueError("MAC check failed")
+
+ def hexverify(self, hex_mac_tag):
+ """Validate the *printable* MAC tag.
+
+ This method is like `verify`.
+
+ :Parameters:
+ hex_mac_tag : string
+ This is the *printable* MAC, as received from the sender.
+ :Raises ValueError:
+ if the MAC does not match. The message has been tampered with
+ or the key is incorrect.
+ """
+
+ self.verify(unhexlify(hex_mac_tag))
+
+ def encrypt_and_digest(self, plaintext):
+ """Encrypt the message and create the MAC tag in one step.
+
+ :Parameters:
+ plaintext : bytes/bytearray/memoryview
+ The entire message to encrypt.
+ :Return:
+ a tuple with two byte strings:
+
+ - the encrypted data
+ - the MAC
+ """
+
+ return self.encrypt(plaintext) + self.encrypt(), self.digest()
+
+ def decrypt_and_verify(self, ciphertext, received_mac_tag):
+ """Decrypted the message and verify its authenticity in one step.
+
+ :Parameters:
+ ciphertext : bytes/bytearray/memoryview
+ The entire message to decrypt.
+ received_mac_tag : byte string
+ This is the *binary* MAC, as received from the sender.
+
+ :Return: the decrypted data (byte string).
+ :Raises ValueError:
+ if the MAC does not match. The message has been tampered with
+ or the key is incorrect.
+ """
+
+ plaintext = self.decrypt(ciphertext) + self.decrypt()
+ self.verify(received_mac_tag)
+ return plaintext
+
+
+def _create_ocb_cipher(factory, **kwargs):
+ """Create a new block cipher, configured in OCB mode.
+
+ :Parameters:
+ factory : module
+ A symmetric cipher module from `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)
diff --git a/frozen_deps/Cryptodome/Cipher/_mode_ocb.pyi b/frozen_deps/Cryptodome/Cipher/_mode_ocb.pyi
new file mode 100644
index 0000000..a1909fc
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_mode_ocb.pyi
@@ -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: ...
diff --git a/frozen_deps/Cryptodome/Cipher/_mode_ofb.py b/frozen_deps/Cryptodome/Cipher/_mode_ofb.py
new file mode 100644
index 0000000..04aaccf
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_mode_ofb.py
@@ -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 = [ self.encrypt, self.decrypt ]
+
+ def encrypt(self, plaintext, output=None):
+ """Encrypt data with the key and the parameters set at initialization.
+
+ A cipher object is stateful: once you have encrypted a message
+ you cannot encrypt (or decrypt) another message using the same
+ object.
+
+ The data to encrypt can be broken up in two or
+ more pieces and `encrypt` can be called multiple times.
+
+ That is, the statement:
+
+ >>> c.encrypt(a) + c.encrypt(b)
+
+ is equivalent to:
+
+ >>> c.encrypt(a+b)
+
+ This function does not add any padding to the plaintext.
+
+ :Parameters:
+ plaintext : bytes/bytearray/memoryview
+ The piece of data to encrypt.
+ It can be of any length.
+ :Keywords:
+ output : bytearray/memoryview
+ The location where the ciphertext must be written to.
+ If ``None``, the ciphertext is returned.
+ :Return:
+ If ``output`` is ``None``, the ciphertext is returned as ``bytes``.
+ Otherwise, ``None``.
+ """
+
+ if self.encrypt not in self._next:
+ raise TypeError("encrypt() cannot be called after decrypt()")
+ self._next = [ self.encrypt ]
+
+ if output is None:
+ ciphertext = create_string_buffer(len(plaintext))
+ else:
+ ciphertext = output
+
+ if not is_writeable_buffer(output):
+ raise TypeError("output must be a bytearray or a writeable memoryview")
+
+ if len(plaintext) != len(output):
+ raise ValueError("output must have the same length as the input"
+ " (%d bytes)" % len(plaintext))
+
+ result = raw_ofb_lib.OFB_encrypt(self._state.get(),
+ c_uint8_ptr(plaintext),
+ c_uint8_ptr(ciphertext),
+ c_size_t(len(plaintext)))
+ if result:
+ raise ValueError("Error %d while encrypting in OFB mode" % result)
+
+ if output is None:
+ return get_raw_buffer(ciphertext)
+ else:
+ return None
+
+ def decrypt(self, ciphertext, output=None):
+ """Decrypt data with the key and the parameters set at initialization.
+
+ A cipher object is stateful: once you have decrypted a message
+ you cannot decrypt (or encrypt) another message with the same
+ object.
+
+ The data to decrypt can be broken up in two or
+ more pieces and `decrypt` can be called multiple times.
+
+ That is, the statement:
+
+ >>> c.decrypt(a) + c.decrypt(b)
+
+ is equivalent to:
+
+ >>> c.decrypt(a+b)
+
+ This function does not remove any padding from the plaintext.
+
+ :Parameters:
+ ciphertext : bytes/bytearray/memoryview
+ The piece of data to decrypt.
+ It can be of any length.
+ :Keywords:
+ output : bytearray/memoryview
+ The location where the plaintext is written to.
+ If ``None``, the plaintext is returned.
+ :Return:
+ If ``output`` is ``None``, the plaintext is returned as ``bytes``.
+ Otherwise, ``None``.
+ """
+
+ if self.decrypt not in self._next:
+ raise TypeError("decrypt() cannot be called after encrypt()")
+ self._next = [ self.decrypt ]
+
+ if output is None:
+ plaintext = create_string_buffer(len(ciphertext))
+ else:
+ plaintext = output
+
+ if not is_writeable_buffer(output):
+ raise TypeError("output must be a bytearray or a writeable memoryview")
+
+ if len(ciphertext) != len(output):
+ raise ValueError("output must have the same length as the input"
+ " (%d bytes)" % len(plaintext))
+
+ result = raw_ofb_lib.OFB_decrypt(self._state.get(),
+ c_uint8_ptr(ciphertext),
+ c_uint8_ptr(plaintext),
+ c_size_t(len(ciphertext)))
+ if result:
+ raise ValueError("Error %d while decrypting in OFB mode" % result)
+
+ if output is None:
+ return get_raw_buffer(plaintext)
+ else:
+ return None
+
+
+def _create_ofb_cipher(factory, **kwargs):
+ """Instantiate a cipher object that performs OFB encryption/decryption.
+
+ :Parameters:
+ factory : module
+ The underlying block cipher, a module from ``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)
diff --git a/frozen_deps/Cryptodome/Cipher/_mode_ofb.pyi b/frozen_deps/Cryptodome/Cipher/_mode_ofb.pyi
new file mode 100644
index 0000000..d28608e
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_mode_ofb.pyi
@@ -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: ...
+
diff --git a/frozen_deps/Cryptodome/Cipher/_mode_openpgp.py b/frozen_deps/Cryptodome/Cipher/_mode_openpgp.py
new file mode 100644
index 0000000..d86ed19
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_mode_openpgp.py
@@ -0,0 +1,206 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# 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)
diff --git a/frozen_deps/Cryptodome/Cipher/_mode_openpgp.pyi b/frozen_deps/Cryptodome/Cipher/_mode_openpgp.pyi
new file mode 100644
index 0000000..14b8105
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_mode_openpgp.pyi
@@ -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: ...
+
diff --git a/frozen_deps/Cryptodome/Cipher/_mode_siv.py b/frozen_deps/Cryptodome/Cipher/_mode_siv.py
new file mode 100644
index 0000000..d10c4dc
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_mode_siv.py
@@ -0,0 +1,392 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# 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 = [self.update, self.encrypt, self.decrypt,
+ self.digest, self.verify]
+
+ def _create_ctr_cipher(self, v):
+ """Create a new CTR cipher from V in SIV mode"""
+
+ v_int = bytes_to_long(v)
+ q = v_int & 0xFFFFFFFFFFFFFFFF7FFFFFFF7FFFFFFF
+ return self._factory.new(
+ self._subkey_cipher,
+ self._factory.MODE_CTR,
+ initial_value=q,
+ nonce=b"",
+ **self._cipher_params)
+
+ def update(self, component):
+ """Protect one associated data component
+
+ For SIV, the associated data is a sequence (*vector*) of non-empty
+ byte strings (*components*).
+
+ This method consumes the next component. It must be called
+ once for each of the components that constitue the associated data.
+
+ Note that the components have clear boundaries, so that:
+
+ >>> cipher.update(b"builtin")
+ >>> cipher.update(b"securely")
+
+ is not equivalent to:
+
+ >>> cipher.update(b"built")
+ >>> cipher.update(b"insecurely")
+
+ If there is no associated data, this method must not be called.
+
+ :Parameters:
+ component : bytes/bytearray/memoryview
+ The next associated data component.
+ """
+
+ if self.update not in self._next:
+ raise TypeError("update() can only be called"
+ " immediately after initialization")
+
+ self._next = [self.update, self.encrypt, self.decrypt,
+ self.digest, self.verify]
+
+ return self._kdf.update(component)
+
+ def encrypt(self, plaintext):
+ """
+ For SIV, encryption and MAC authentication must take place at the same
+ point. This method shall not be used.
+
+ Use `encrypt_and_digest` instead.
+ """
+
+ raise TypeError("encrypt() not allowed for SIV mode."
+ " Use encrypt_and_digest() instead.")
+
+ def decrypt(self, ciphertext):
+ """
+ For SIV, decryption and verification must take place at the same
+ point. This method shall not be used.
+
+ Use `decrypt_and_verify` instead.
+ """
+
+ raise TypeError("decrypt() not allowed for SIV mode."
+ " Use decrypt_and_verify() instead.")
+
+ def digest(self):
+ """Compute the *binary* MAC tag.
+
+ The caller invokes this function at the very end.
+
+ This method returns the MAC that shall be sent to the receiver,
+ together with the ciphertext.
+
+ :Return: the MAC, as a byte string.
+ """
+
+ if self.digest not in self._next:
+ raise TypeError("digest() cannot be called when decrypting"
+ " or validating a message")
+ self._next = [self.digest]
+ if self._mac_tag is None:
+ self._mac_tag = self._kdf.derive()
+ return self._mac_tag
+
+ def hexdigest(self):
+ """Compute the *printable* MAC tag.
+
+ This method is like `digest`.
+
+ :Return: the MAC, as a hexadecimal string.
+ """
+ return "".join(["%02x" % bord(x) for x in self.digest()])
+
+ def verify(self, received_mac_tag):
+ """Validate the *binary* MAC tag.
+
+ The caller invokes this function at the very end.
+
+ This method checks if the decrypted message is indeed valid
+ (that is, if the key is correct) and it has not been
+ tampered with while in transit.
+
+ :Parameters:
+ received_mac_tag : bytes/bytearray/memoryview
+ This is the *binary* MAC, as received from the sender.
+ :Raises ValueError:
+ if the MAC does not match. The message has been tampered with
+ or the key is incorrect.
+ """
+
+ if self.verify not in self._next:
+ raise TypeError("verify() cannot be called"
+ " when encrypting a message")
+ self._next = [self.verify]
+
+ if self._mac_tag is None:
+ self._mac_tag = self._kdf.derive()
+
+ secret = get_random_bytes(16)
+
+ mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag)
+ mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag)
+
+ if mac1.digest() != mac2.digest():
+ raise ValueError("MAC check failed")
+
+ def hexverify(self, hex_mac_tag):
+ """Validate the *printable* MAC tag.
+
+ This method is like `verify`.
+
+ :Parameters:
+ hex_mac_tag : string
+ This is the *printable* MAC, as received from the sender.
+ :Raises ValueError:
+ if the MAC does not match. The message has been tampered with
+ or the key is incorrect.
+ """
+
+ self.verify(unhexlify(hex_mac_tag))
+
+ def encrypt_and_digest(self, plaintext, output=None):
+ """Perform encrypt() and digest() in one step.
+
+ :Parameters:
+ plaintext : bytes/bytearray/memoryview
+ The piece of data to encrypt.
+ :Keywords:
+ output : bytearray/memoryview
+ The location where the ciphertext must be written to.
+ If ``None``, the ciphertext is returned.
+ :Return:
+ a tuple with two items:
+
+ - the ciphertext, as ``bytes``
+ - the MAC tag, as ``bytes``
+
+ The first item becomes ``None`` when the ``output`` parameter
+ specified a location for the result.
+ """
+
+ if self.encrypt not in self._next:
+ raise TypeError("encrypt() can only be called after"
+ " initialization or an update()")
+
+ self._next = [ self.digest ]
+
+ # Compute V (MAC)
+ if hasattr(self, 'nonce'):
+ self._kdf.update(self.nonce)
+ self._kdf.update(plaintext)
+ self._mac_tag = self._kdf.derive()
+
+ cipher = self._create_ctr_cipher(self._mac_tag)
+
+ return cipher.encrypt(plaintext, output=output), self._mac_tag
+
+ def decrypt_and_verify(self, ciphertext, mac_tag, output=None):
+ """Perform decryption and verification in one step.
+
+ A cipher object is stateful: once you have decrypted a message
+ you cannot decrypt (or encrypt) another message with the same
+ object.
+
+ You cannot reuse an object for encrypting
+ or decrypting other data with the same key.
+
+ This function does not remove any padding from the plaintext.
+
+ :Parameters:
+ ciphertext : bytes/bytearray/memoryview
+ The piece of data to decrypt.
+ It can be of any length.
+ mac_tag : bytes/bytearray/memoryview
+ This is the *binary* MAC, as received from the sender.
+ :Keywords:
+ output : bytearray/memoryview
+ The location where the plaintext must be written to.
+ If ``None``, the plaintext is returned.
+ :Return: the plaintext as ``bytes`` or ``None`` when the ``output``
+ parameter specified a location for the result.
+ :Raises ValueError:
+ if the MAC does not match. The message has been tampered with
+ or the key is incorrect.
+ """
+
+ if self.decrypt not in self._next:
+ raise TypeError("decrypt() can only be called"
+ " after initialization or an update()")
+ self._next = [ self.verify ]
+
+ # Take the MAC and start the cipher for decryption
+ self._cipher = self._create_ctr_cipher(mac_tag)
+
+ plaintext = self._cipher.decrypt(ciphertext, output=output)
+
+ if hasattr(self, 'nonce'):
+ self._kdf.update(self.nonce)
+ self._kdf.update(plaintext if output is None else output)
+ self.verify(mac_tag)
+
+ return plaintext
+
+
+def _create_siv_cipher(factory, **kwargs):
+ """Create a new block cipher, configured in
+ Synthetic Initializaton Vector (SIV) mode.
+
+ :Parameters:
+
+ factory : object
+ A symmetric cipher module from `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)
diff --git a/frozen_deps/Cryptodome/Cipher/_mode_siv.pyi b/frozen_deps/Cryptodome/Cipher/_mode_siv.pyi
new file mode 100644
index 0000000..2934f23
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_mode_siv.pyi
@@ -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: ...
diff --git a/frozen_deps/Cryptodome/Cipher/_raw_aes.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Cipher/_raw_aes.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..e62f4d1
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_raw_aes.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Cipher/_raw_aesni.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Cipher/_raw_aesni.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..b92e170
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_raw_aesni.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Cipher/_raw_arc2.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Cipher/_raw_arc2.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..07a720a
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_raw_arc2.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Cipher/_raw_blowfish.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Cipher/_raw_blowfish.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..05abfd1
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_raw_blowfish.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Cipher/_raw_cast.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Cipher/_raw_cast.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..2523fcb
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_raw_cast.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Cipher/_raw_cbc.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Cipher/_raw_cbc.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..1b013f3
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_raw_cbc.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Cipher/_raw_cfb.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Cipher/_raw_cfb.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..6a28991
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_raw_cfb.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Cipher/_raw_ctr.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Cipher/_raw_ctr.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..0529cf8
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_raw_ctr.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Cipher/_raw_des.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Cipher/_raw_des.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..1d73854
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_raw_des.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Cipher/_raw_des3.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Cipher/_raw_des3.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..8c4afa5
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_raw_des3.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Cipher/_raw_ecb.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Cipher/_raw_ecb.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..0775c0b
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_raw_ecb.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Cipher/_raw_eksblowfish.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Cipher/_raw_eksblowfish.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..979fe63
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_raw_eksblowfish.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Cipher/_raw_ocb.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Cipher/_raw_ocb.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..d545618
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_raw_ocb.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Cipher/_raw_ofb.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Cipher/_raw_ofb.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..7157784
--- /dev/null
+++ b/frozen_deps/Cryptodome/Cipher/_raw_ofb.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Hash/BLAKE2b.py b/frozen_deps/Cryptodome/Hash/BLAKE2b.py
new file mode 100644
index 0000000..d7e968f
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/BLAKE2b.py
@@ -0,0 +1,247 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# 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_bytes' not in range 8..512, "
+ "with steps of 8")
+ digest_bytes = digest_bits // 8
+
+ key = kwargs.pop("key", b"")
+ if len(key) > 64:
+ raise ValueError("BLAKE2s key cannot exceed 64 bytes")
+
+ if kwargs:
+ raise TypeError("Unknown parameters: " + str(kwargs))
+
+ return BLAKE2b_Hash(data, key, digest_bytes, update_after_digest)
diff --git a/frozen_deps/Cryptodome/Hash/BLAKE2b.pyi b/frozen_deps/Cryptodome/Hash/BLAKE2b.pyi
new file mode 100644
index 0000000..ac3bf57
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/BLAKE2b.pyi
@@ -0,0 +1,31 @@
+from typing import Any, Union
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class BLAKE2b_Hash(object):
+ block_size: int
+ digest_size: int
+ oid: str
+
+ def __init__(self,
+ data: Buffer,
+ key: Buffer,
+ digest_bytes: bytes,
+ update_after_digest: bool) -> None: ...
+ def update(self, data: Buffer) -> BLAKE2b_Hash: ...
+ def digest(self) -> bytes: ...
+ def hexdigest(self) -> str: ...
+ def verify(self, mac_tag: Buffer) -> None: ...
+ def hexverify(self, hex_mac_tag: str) -> None: ...
+ def new(self,
+ data: Buffer = ...,
+ digest_bytes: int = ...,
+ digest_bits: int = ...,
+ key: Buffer = ...,
+ update_after_digest: bool = ...) -> BLAKE2b_Hash: ...
+
+def new(data: Buffer = ...,
+ digest_bytes: int = ...,
+ digest_bits: int = ...,
+ key: Buffer = ...,
+ update_after_digest: bool = ...) -> BLAKE2b_Hash: ...
diff --git a/frozen_deps/Cryptodome/Hash/BLAKE2s.py b/frozen_deps/Cryptodome/Hash/BLAKE2s.py
new file mode 100644
index 0000000..a16b515
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/BLAKE2s.py
@@ -0,0 +1,247 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# 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_bytes' not in range 8..256, "
+ "with steps of 8")
+ digest_bytes = digest_bits // 8
+
+ key = kwargs.pop("key", b"")
+ if len(key) > 32:
+ raise ValueError("BLAKE2s key cannot exceed 32 bytes")
+
+ if kwargs:
+ raise TypeError("Unknown parameters: " + str(kwargs))
+
+ return BLAKE2s_Hash(data, key, digest_bytes, update_after_digest)
diff --git a/frozen_deps/Cryptodome/Hash/BLAKE2s.pyi b/frozen_deps/Cryptodome/Hash/BLAKE2s.pyi
new file mode 100644
index 0000000..374b3a4
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/BLAKE2s.pyi
@@ -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: ...
diff --git a/frozen_deps/Cryptodome/Hash/CMAC.py b/frozen_deps/Cryptodome/Hash/CMAC.py
new file mode 100644
index 0000000..df69f00
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/CMAC.py
@@ -0,0 +1,305 @@
+# -*- 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.
+# ===================================================================
+
+import sys
+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
+
+if sys.version_info[:2] == (2, 6):
+ memoryview = bytes
+
+# The size of the authentication tag produced by the MAC.
+digest_size = None
+
+
+def _shift_bytes(bs, xor_lsb=0):
+ num = (bytes_to_long(bs) << 1) ^ xor_lsb
+ return long_to_bytes(num, len(bs))[-len(bs):]
+
+
+class CMAC(object):
+ """A CMAC hash object.
+ Do not instantiate directly. Use the :func:`new` function.
+
+ :ivar digest_size: the size in bytes of the resulting MAC tag
+ :vartype digest_size: integer
+ """
+
+ digest_size = None
+
+ def __init__(self, key, msg, ciphermod, cipher_params, mac_len,
+ update_after_digest):
+
+ self.digest_size = mac_len
+
+ self._key = _copy_bytes(None, None, key)
+ self._factory = ciphermod
+ self._cipher_params = cipher_params
+ self._block_size = bs = ciphermod.block_size
+ self._mac_tag = None
+ self._update_after_digest = update_after_digest
+
+ # Section 5.3 of NIST SP 800 38B and Appendix B
+ if bs == 8:
+ const_Rb = 0x1B
+ self._max_size = 8 * (2 ** 21)
+ elif bs == 16:
+ const_Rb = 0x87
+ self._max_size = 16 * (2 ** 48)
+ else:
+ raise TypeError("CMAC requires a cipher with a block size"
+ " of 8 or 16 bytes, not %d" % bs)
+
+ # Compute sub-keys
+ zero_block = b'\x00' * bs
+ self._ecb = ciphermod.new(key,
+ ciphermod.MODE_ECB,
+ **self._cipher_params)
+ L = self._ecb.encrypt(zero_block)
+ if bord(L[0]) & 0x80:
+ self._k1 = _shift_bytes(L, const_Rb)
+ else:
+ self._k1 = _shift_bytes(L)
+ if bord(self._k1[0]) & 0x80:
+ self._k2 = _shift_bytes(self._k1, const_Rb)
+ else:
+ self._k2 = _shift_bytes(self._k1)
+
+ # Initialize CBC cipher with zero IV
+ self._cbc = ciphermod.new(key,
+ ciphermod.MODE_CBC,
+ zero_block,
+ **self._cipher_params)
+
+ # Cache for outstanding data to authenticate
+ self._cache = bytearray(bs)
+ self._cache_n = 0
+
+ # Last piece of ciphertext produced
+ self._last_ct = zero_block
+
+ # Last block that was encrypted with AES
+ self._last_pt = None
+
+ # Counter for total message size
+ self._data_size = 0
+
+ if msg:
+ self.update(msg)
+
+ def update(self, msg):
+ """Authenticate the next chunk of message.
+
+ Args:
+ data (byte string/byte array/memoryview): The next chunk of data
+ """
+
+ if self._mac_tag is not None and not self._update_after_digest:
+ raise TypeError("update() cannot be called after digest() or verify()")
+
+ self._data_size += len(msg)
+ bs = self._block_size
+
+ if self._cache_n > 0:
+ filler = min(bs - self._cache_n, len(msg))
+ self._cache[self._cache_n:self._cache_n+filler] = msg[:filler]
+ self._cache_n += filler
+
+ if self._cache_n < bs:
+ return self
+
+ msg = memoryview(msg)[filler:]
+ self._update(self._cache)
+ self._cache_n = 0
+
+ remain = len(msg) % bs
+ if remain > 0:
+ self._update(msg[:-remain])
+ self._cache[:remain] = msg[-remain:]
+ else:
+ self._update(msg)
+ self._cache_n = remain
+ return self
+
+ def _update(self, data_block):
+ """Update a block aligned to the block boundary"""
+
+ bs = self._block_size
+ assert len(data_block) % bs == 0
+
+ if len(data_block) == 0:
+ return
+
+ ct = self._cbc.encrypt(data_block)
+ if len(data_block) == bs:
+ second_last = self._last_ct
+ else:
+ second_last = ct[-bs*2:-bs]
+ self._last_ct = ct[-bs:]
+ self._last_pt = strxor(second_last, data_block[-bs:])
+
+ def copy(self):
+ """Return a copy ("clone") of the CMAC object.
+
+ The copy will have the same internal state as the original CMAC
+ object.
+ This can be used to efficiently compute the MAC tag of byte
+ strings that share a common initial substring.
+
+ :return: An :class:`CMAC`
+ """
+
+ obj = self.__new__(CMAC)
+ obj.__dict__ = self.__dict__.copy()
+ obj._cbc = self._factory.new(self._key,
+ self._factory.MODE_CBC,
+ self._last_ct,
+ **self._cipher_params)
+ obj._cache = self._cache[:]
+ obj._last_ct = self._last_ct[:]
+ return obj
+
+ def digest(self):
+ """Return the **binary** (non-printable) MAC tag of the message
+ that has been authenticated so far.
+
+ :return: The MAC tag, computed over the data processed so far.
+ Binary form.
+ :rtype: byte string
+ """
+
+ bs = self._block_size
+
+ if self._mac_tag is not None and not self._update_after_digest:
+ return self._mac_tag
+
+ if self._data_size > self._max_size:
+ raise ValueError("MAC is unsafe for this message")
+
+ if self._cache_n == 0 and self._data_size > 0:
+ # Last block was full
+ pt = strxor(self._last_pt, self._k1)
+ else:
+ # Last block is partial (or message length is zero)
+ partial = self._cache[:]
+ partial[self._cache_n:] = b'\x80' + b'\x00' * (bs - self._cache_n - 1)
+ pt = strxor(strxor(self._last_ct, partial), self._k2)
+
+ self._mac_tag = self._ecb.encrypt(pt)[:self.digest_size]
+
+ return self._mac_tag
+
+ def hexdigest(self):
+ """Return the **printable** MAC tag of the message authenticated so far.
+
+ :return: The MAC tag, computed over the data processed so far.
+ Hexadecimal encoded.
+ :rtype: string
+ """
+
+ return "".join(["%02x" % bord(x)
+ for x in tuple(self.digest())])
+
+ def verify(self, mac_tag):
+ """Verify that a given **binary** MAC (computed by another party)
+ is valid.
+
+ Args:
+ mac_tag (byte string/byte array/memoryview): the expected MAC of the message.
+
+ Raises:
+ ValueError: if the MAC does not match. It means that the message
+ has been tampered with or that the MAC key is incorrect.
+ """
+
+ secret = get_random_bytes(16)
+
+ mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag)
+ mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest())
+
+ if mac1.digest() != mac2.digest():
+ raise ValueError("MAC check failed")
+
+ def hexverify(self, hex_mac_tag):
+ """Return the **printable** MAC tag of the message authenticated so far.
+
+ :return: The MAC tag, computed over the data processed so far.
+ Hexadecimal encoded.
+ :rtype: string
+ """
+
+ self.verify(unhexlify(tobytes(hex_mac_tag)))
+
+
+def new(key, msg=None, ciphermod=None, cipher_params=None, mac_len=None,
+ update_after_digest=False):
+ """Create a new MAC object.
+
+ Args:
+ key (byte string/byte array/memoryview):
+ key for the CMAC object.
+ The key must be valid for the underlying cipher algorithm.
+ For instance, it must be 16 bytes long for AES-128.
+ ciphermod (module):
+ A cipher module from :mod:`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)
diff --git a/frozen_deps/Cryptodome/Hash/CMAC.pyi b/frozen_deps/Cryptodome/Hash/CMAC.pyi
new file mode 100644
index 0000000..33773aa
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/CMAC.pyi
@@ -0,0 +1,30 @@
+from types import ModuleType
+from typing import Union, Dict
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+digest_size: int
+
+class CMAC(object):
+ digest_size: int
+
+ def __init__(self,
+ key: Buffer,
+ msg: Buffer,
+ ciphermod: ModuleType,
+ cipher_params: dict,
+ mac_len: int, update_after_digest: bool) -> None: ...
+ def update(self, data: Buffer) -> CMAC: ...
+ def copy(self) -> CMAC: ...
+ def digest(self) -> bytes: ...
+ def hexdigest(self) -> str: ...
+ def verify(self, mac_tag: Buffer) -> None: ...
+ def hexverify(self, hex_mac_tag: str) -> None: ...
+
+
+def new(key: Buffer,
+ msg: Buffer = ...,
+ ciphermod: ModuleType = ...,
+ cipher_params: Dict = ...,
+ mac_len: int = ...,
+ update_after_digest: bool = ...) -> CMAC: ...
diff --git a/frozen_deps/Cryptodome/Hash/HMAC.py b/frozen_deps/Cryptodome/Hash/HMAC.py
new file mode 100644
index 0000000..ac94b20
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/HMAC.py
@@ -0,0 +1,213 @@
+#
+# HMAC.py - Implements the HMAC algorithm as described by RFC 2104.
+#
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# 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, _memoryview
+
+from binascii import unhexlify
+
+from Cryptodome.Hash import MD5
+from Cryptodome.Hash import BLAKE2s
+from Cryptodome.Util.strxor import strxor
+from Cryptodome.Random import get_random_bytes
+
+__all__ = ['new', 'HMAC']
+
+
+class HMAC(object):
+ """An HMAC hash object.
+ Do not instantiate directly. Use the :func:`new` function.
+
+ :ivar digest_size: the size in bytes of the resulting MAC tag
+ :vartype digest_size: integer
+ """
+
+ def __init__(self, key, msg=b"", digestmod=None):
+
+ if digestmod is None:
+ digestmod = MD5
+
+ if msg is None:
+ msg = b""
+
+ # Size of the MAC tag
+ self.digest_size = digestmod.digest_size
+
+ self._digestmod = digestmod
+
+ if isinstance(key, _memoryview):
+ key = key.tobytes()
+
+ try:
+ if len(key) <= digestmod.block_size:
+ # Step 1 or 2
+ key_0 = key + b"\x00" * (digestmod.block_size - len(key))
+ else:
+ # Step 3
+ hash_k = digestmod.new(key).digest()
+ key_0 = hash_k + b"\x00" * (digestmod.block_size - len(hash_k))
+ except AttributeError:
+ # Not all hash types have "block_size"
+ raise ValueError("Hash type incompatible to HMAC")
+
+ # Step 4
+ key_0_ipad = strxor(key_0, b"\x36" * len(key_0))
+
+ # Start step 5 and 6
+ self._inner = digestmod.new(key_0_ipad)
+ self._inner.update(msg)
+
+ # Step 7
+ key_0_opad = strxor(key_0, b"\x5c" * len(key_0))
+
+ # Start step 8 and 9
+ self._outer = digestmod.new(key_0_opad)
+
+ def update(self, msg):
+ """Authenticate the next chunk of message.
+
+ Args:
+ data (byte string/byte array/memoryview): The next chunk of data
+ """
+
+ self._inner.update(msg)
+ return self
+
+ def _pbkdf2_hmac_assist(self, first_digest, iterations):
+ """Carry out the expensive inner loop for PBKDF2-HMAC"""
+
+ result = self._digestmod._pbkdf2_hmac_assist(
+ self._inner,
+ self._outer,
+ first_digest,
+ iterations)
+ return result
+
+ def copy(self):
+ """Return a copy ("clone") of the HMAC object.
+
+ The copy will have the same internal state as the original HMAC
+ object.
+ This can be used to efficiently compute the MAC tag of byte
+ strings that share a common initial substring.
+
+ :return: An :class:`HMAC`
+ """
+
+ new_hmac = HMAC(b"fake key", digestmod=self._digestmod)
+
+ # Syncronize the state
+ new_hmac._inner = self._inner.copy()
+ new_hmac._outer = self._outer.copy()
+
+ return new_hmac
+
+ def digest(self):
+ """Return the **binary** (non-printable) MAC tag of the message
+ authenticated so far.
+
+ :return: The MAC tag digest, computed over the data processed so far.
+ Binary form.
+ :rtype: byte string
+ """
+
+ frozen_outer_hash = self._outer.copy()
+ frozen_outer_hash.update(self._inner.digest())
+ return frozen_outer_hash.digest()
+
+ def verify(self, mac_tag):
+ """Verify that a given **binary** MAC (computed by another party)
+ is valid.
+
+ Args:
+ mac_tag (byte string/byte string/memoryview): the expected MAC of the message.
+
+ Raises:
+ ValueError: if the MAC does not match. It means that the message
+ has been tampered with or that the MAC key is incorrect.
+ """
+
+ secret = get_random_bytes(16)
+
+ mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag)
+ mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest())
+
+ if mac1.digest() != mac2.digest():
+ raise ValueError("MAC check failed")
+
+ def hexdigest(self):
+ """Return the **printable** MAC tag of the message authenticated so far.
+
+ :return: The MAC tag, computed over the data processed so far.
+ Hexadecimal encoded.
+ :rtype: string
+ """
+
+ return "".join(["%02x" % bord(x)
+ for x in tuple(self.digest())])
+
+ def hexverify(self, hex_mac_tag):
+ """Verify that a given **printable** MAC (computed by another party)
+ is valid.
+
+ Args:
+ hex_mac_tag (string): the expected MAC of the message,
+ as a hexadecimal string.
+
+ Raises:
+ ValueError: if the MAC does not match. It means that the message
+ has been tampered with or that the MAC key is incorrect.
+ """
+
+ self.verify(unhexlify(tobytes(hex_mac_tag)))
+
+
+def new(key, msg=b"", digestmod=None):
+ """Create a new MAC object.
+
+ Args:
+ key (bytes/bytearray/memoryview):
+ key for the MAC object.
+ It must be long enough to match the expected security level of the
+ MAC.
+ msg (bytes/bytearray/memoryview):
+ Optional. The very first chunk of the message to authenticate.
+ It is equivalent to an early call to :meth:`HMAC.update`.
+ digestmod (module):
+ The hash to use to implement the HMAC.
+ Default is :mod:`Cryptodome.Hash.MD5`.
+
+ Returns:
+ An :class:`HMAC` object
+ """
+
+ return HMAC(key, msg, digestmod)
diff --git a/frozen_deps/Cryptodome/Hash/HMAC.pyi b/frozen_deps/Cryptodome/Hash/HMAC.pyi
new file mode 100644
index 0000000..b577230
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/HMAC.pyi
@@ -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: ...
diff --git a/frozen_deps/Cryptodome/Hash/MD2.py b/frozen_deps/Cryptodome/Hash/MD2.py
new file mode 100644
index 0000000..47ecc05
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/MD2.py
@@ -0,0 +1,166 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# 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
diff --git a/frozen_deps/Cryptodome/Hash/MD2.pyi b/frozen_deps/Cryptodome/Hash/MD2.pyi
new file mode 100644
index 0000000..95a97a9
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/MD2.pyi
@@ -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
diff --git a/frozen_deps/Cryptodome/Hash/MD4.py b/frozen_deps/Cryptodome/Hash/MD4.py
new file mode 100644
index 0000000..668fa65
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/MD4.py
@@ -0,0 +1,185 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# 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
diff --git a/frozen_deps/Cryptodome/Hash/MD4.pyi b/frozen_deps/Cryptodome/Hash/MD4.pyi
new file mode 100644
index 0000000..a9a7295
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/MD4.pyi
@@ -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
diff --git a/frozen_deps/Cryptodome/Hash/MD5.py b/frozen_deps/Cryptodome/Hash/MD5.py
new file mode 100644
index 0000000..8f573a9
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/MD5.py
@@ -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)
diff --git a/frozen_deps/Cryptodome/Hash/MD5.pyi b/frozen_deps/Cryptodome/Hash/MD5.pyi
new file mode 100644
index 0000000..d819556
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/MD5.pyi
@@ -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
diff --git a/frozen_deps/Cryptodome/Hash/Poly1305.py b/frozen_deps/Cryptodome/Hash/Poly1305.py
new file mode 100644
index 0000000..c03f522
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/Poly1305.py
@@ -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
diff --git a/frozen_deps/Cryptodome/Hash/Poly1305.pyi b/frozen_deps/Cryptodome/Hash/Poly1305.pyi
new file mode 100644
index 0000000..f97a14a
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/Poly1305.pyi
@@ -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: ...
diff --git a/frozen_deps/Cryptodome/Hash/RIPEMD.py b/frozen_deps/Cryptodome/Hash/RIPEMD.py
new file mode 100644
index 0000000..35ad576
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/RIPEMD.py
@@ -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
diff --git a/frozen_deps/Cryptodome/Hash/RIPEMD.pyi b/frozen_deps/Cryptodome/Hash/RIPEMD.pyi
new file mode 100644
index 0000000..cfb2252
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/RIPEMD.pyi
@@ -0,0 +1,3 @@
+# This file exists for backward compatibility with old code that refers to
+# Cryptodome.Hash.SHA
+
diff --git a/frozen_deps/Cryptodome/Hash/RIPEMD160.py b/frozen_deps/Cryptodome/Hash/RIPEMD160.py
new file mode 100644
index 0000000..f959027
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/RIPEMD160.py
@@ -0,0 +1,169 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# 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
diff --git a/frozen_deps/Cryptodome/Hash/RIPEMD160.pyi b/frozen_deps/Cryptodome/Hash/RIPEMD160.pyi
new file mode 100644
index 0000000..b619473
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/RIPEMD160.pyi
@@ -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
diff --git a/frozen_deps/Cryptodome/Hash/SHA.py b/frozen_deps/Cryptodome/Hash/SHA.py
new file mode 100644
index 0000000..95f8745
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHA.py
@@ -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
diff --git a/frozen_deps/Cryptodome/Hash/SHA.pyi b/frozen_deps/Cryptodome/Hash/SHA.pyi
new file mode 100644
index 0000000..7d01a5f
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHA.pyi
@@ -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
diff --git a/frozen_deps/Cryptodome/Hash/SHA1.py b/frozen_deps/Cryptodome/Hash/SHA1.py
new file mode 100644
index 0000000..dea51bc
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHA1.py
@@ -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)
diff --git a/frozen_deps/Cryptodome/Hash/SHA1.pyi b/frozen_deps/Cryptodome/Hash/SHA1.pyi
new file mode 100644
index 0000000..d6c8e25
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHA1.pyi
@@ -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
diff --git a/frozen_deps/Cryptodome/Hash/SHA224.py b/frozen_deps/Cryptodome/Hash/SHA224.py
new file mode 100644
index 0000000..fca7622
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHA224.py
@@ -0,0 +1,186 @@
+# -*- 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 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_sha224_lib = load_pycryptodome_raw_lib("Cryptodome.Hash._SHA224",
+ """
+ int SHA224_init(void **shaState);
+ int SHA224_destroy(void *shaState);
+ int SHA224_update(void *hs,
+ const uint8_t *buf,
+ size_t len);
+ int SHA224_digest(const void *shaState,
+ uint8_t *digest,
+ size_t digest_size);
+ int SHA224_copy(const void *src, void *dst);
+
+ int SHA224_pbkdf2_hmac_assist(const void *inner,
+ const void *outer,
+ const uint8_t *first_digest,
+ uint8_t *final_digest,
+ size_t iterations,
+ size_t digest_size);
+ """)
+
+class SHA224Hash(object):
+ """A SHA-224 hash object.
+ Do not instantiate directly.
+ Use the :func:`new` function.
+
+ :ivar oid: ASN.1 Object ID
+ :vartype oid: string
+
+ :ivar block_size: the size in bytes of the internal message block,
+ input to the compression function
+ :vartype block_size: integer
+
+ :ivar digest_size: the size in bytes of the resulting hash
+ :vartype digest_size: integer
+ """
+
+ # The size of the resulting hash in bytes.
+ digest_size = 28
+ # The internal block size of the hash algorithm in bytes.
+ block_size = 64
+ # ASN.1 Object ID
+ oid = '2.16.840.1.101.3.4.2.4'
+
+ def __init__(self, data=None):
+ state = VoidPointer()
+ result = _raw_sha224_lib.SHA224_init(state.address_of())
+ if result:
+ raise ValueError("Error %d while instantiating SHA224"
+ % result)
+ self._state = SmartPointer(state.get(),
+ _raw_sha224_lib.SHA224_destroy)
+ if data:
+ self.update(data)
+
+ def update(self, data):
+ """Continue hashing of a message by consuming the next chunk of data.
+
+ Args:
+ data (byte string/byte array/memoryview): The next chunk of the message being hashed.
+ """
+
+ result = _raw_sha224_lib.SHA224_update(self._state.get(),
+ c_uint8_ptr(data),
+ c_size_t(len(data)))
+ if result:
+ raise ValueError("Error %d while hashing data with SHA224"
+ % result)
+
+ def digest(self):
+ """Return the **binary** (non-printable) digest of the message that has been hashed so far.
+
+ :return: The hash digest, computed over the data processed so far.
+ Binary form.
+ :rtype: byte string
+ """
+
+ bfr = create_string_buffer(self.digest_size)
+ result = _raw_sha224_lib.SHA224_digest(self._state.get(),
+ bfr,
+ c_size_t(self.digest_size))
+ if result:
+ raise ValueError("Error %d while making SHA224 digest"
+ % result)
+
+ return get_raw_buffer(bfr)
+
+ def hexdigest(self):
+ """Return the **printable** digest of the message that has been hashed so far.
+
+ :return: The hash digest, computed over the data processed so far.
+ Hexadecimal encoded.
+ :rtype: string
+ """
+
+ return "".join(["%02x" % bord(x) for x in self.digest()])
+
+ def copy(self):
+ """Return a copy ("clone") of the hash object.
+
+ The copy will have the same internal state as the original hash
+ object.
+ This can be used to efficiently compute the digests of strings that
+ share a common initial substring.
+
+ :return: A hash object of the same type
+ """
+
+ clone = SHA224Hash()
+ result = _raw_sha224_lib.SHA224_copy(self._state.get(),
+ clone._state.get())
+ if result:
+ raise ValueError("Error %d while copying SHA224" % result)
+ return clone
+
+ def new(self, data=None):
+ """Create a fresh SHA-224 hash object."""
+
+ return SHA224Hash(data)
+
+
+def new(data=None):
+ """Create a new hash object.
+
+ :parameter data:
+ Optional. The very first chunk of the message to hash.
+ It is equivalent to an early call to :meth:`SHA224Hash.update`.
+ :type data: byte string/byte array/memoryview
+
+ :Return: A :class:`SHA224Hash` hash object
+ """
+ return SHA224Hash().new(data)
+
+
+# The size of the resulting hash in bytes.
+digest_size = SHA224Hash.digest_size
+
+# The internal block size of the hash algorithm in bytes.
+block_size = SHA224Hash.block_size
+
+
+def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations):
+ """Compute the expensive inner loop in PBKDF-HMAC."""
+
+ assert iterations > 0
+
+ bfr = create_string_buffer(len(first_digest));
+ result = _raw_sha224_lib.SHA224_pbkdf2_hmac_assist(
+ inner._state.get(),
+ outer._state.get(),
+ first_digest,
+ bfr,
+ c_size_t(iterations),
+ c_size_t(len(first_digest)))
+
+ if result:
+ raise ValueError("Error %d with PBKDF2-HMAC assist for SHA224" % result)
+
+ return get_raw_buffer(bfr)
diff --git a/frozen_deps/Cryptodome/Hash/SHA224.pyi b/frozen_deps/Cryptodome/Hash/SHA224.pyi
new file mode 100644
index 0000000..613a7f9
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHA224.pyi
@@ -0,0 +1,19 @@
+from typing import Union, Optional
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class SHA224Hash(object):
+ digest_size: int
+ block_size: int
+ oid: str
+
+ def __init__(self, data: Optional[Buffer] = ...) -> None: ...
+ def update(self, data: Buffer) -> None: ...
+ def digest(self) -> bytes: ...
+ def hexdigest(self) -> str: ...
+ def copy(self) -> SHA224Hash: ...
+ def new(self, data: Optional[Buffer] = ...) -> SHA224Hash: ...
+
+def new(data: Optional[Buffer] = ...) -> SHA224Hash: ...
+digest_size: int
+block_size: int
diff --git a/frozen_deps/Cryptodome/Hash/SHA256.py b/frozen_deps/Cryptodome/Hash/SHA256.py
new file mode 100644
index 0000000..c1a81b1
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHA256.py
@@ -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 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_sha256_lib = load_pycryptodome_raw_lib("Cryptodome.Hash._SHA256",
+ """
+ int SHA256_init(void **shaState);
+ int SHA256_destroy(void *shaState);
+ int SHA256_update(void *hs,
+ const uint8_t *buf,
+ size_t len);
+ int SHA256_digest(const void *shaState,
+ uint8_t *digest,
+ size_t digest_size);
+ int SHA256_copy(const void *src, void *dst);
+
+ int SHA256_pbkdf2_hmac_assist(const void *inner,
+ const void *outer,
+ const uint8_t *first_digest,
+ uint8_t *final_digest,
+ size_t iterations,
+ size_t digest_size);
+ """)
+
+class SHA256Hash(object):
+ """A SHA-256 hash object.
+ Do not instantiate directly. Use the :func:`new` function.
+
+ :ivar oid: ASN.1 Object ID
+ :vartype oid: string
+
+ :ivar block_size: the size in bytes of the internal message block,
+ input to the compression function
+ :vartype block_size: integer
+
+ :ivar digest_size: the size in bytes of the resulting hash
+ :vartype digest_size: integer
+ """
+
+ # The size of the resulting hash in bytes.
+ digest_size = 32
+ # The internal block size of the hash algorithm in bytes.
+ block_size = 64
+ # ASN.1 Object ID
+ oid = "2.16.840.1.101.3.4.2.1"
+
+ def __init__(self, data=None):
+ state = VoidPointer()
+ result = _raw_sha256_lib.SHA256_init(state.address_of())
+ if result:
+ raise ValueError("Error %d while instantiating SHA256"
+ % result)
+ self._state = SmartPointer(state.get(),
+ _raw_sha256_lib.SHA256_destroy)
+ if data:
+ self.update(data)
+
+ def update(self, data):
+ """Continue hashing of a message by consuming the next chunk of data.
+
+ Args:
+ data (byte string/byte array/memoryview): The next chunk of the message being hashed.
+ """
+
+ result = _raw_sha256_lib.SHA256_update(self._state.get(),
+ c_uint8_ptr(data),
+ c_size_t(len(data)))
+ if result:
+ raise ValueError("Error %d while hashing data with SHA256"
+ % result)
+
+ def digest(self):
+ """Return the **binary** (non-printable) digest of the message that has been hashed so far.
+
+ :return: The hash digest, computed over the data processed so far.
+ Binary form.
+ :rtype: byte string
+ """
+
+ bfr = create_string_buffer(self.digest_size)
+ result = _raw_sha256_lib.SHA256_digest(self._state.get(),
+ bfr,
+ c_size_t(self.digest_size))
+ if result:
+ raise ValueError("Error %d while making SHA256 digest"
+ % result)
+
+ return get_raw_buffer(bfr)
+
+ def hexdigest(self):
+ """Return the **printable** digest of the message that has been hashed so far.
+
+ :return: The hash digest, computed over the data processed so far.
+ Hexadecimal encoded.
+ :rtype: string
+ """
+
+ return "".join(["%02x" % bord(x) for x in self.digest()])
+
+ def copy(self):
+ """Return a copy ("clone") of the hash object.
+
+ The copy will have the same internal state as the original hash
+ object.
+ This can be used to efficiently compute the digests of strings that
+ share a common initial substring.
+
+ :return: A hash object of the same type
+ """
+
+ clone = SHA256Hash()
+ result = _raw_sha256_lib.SHA256_copy(self._state.get(),
+ clone._state.get())
+ if result:
+ raise ValueError("Error %d while copying SHA256" % result)
+ return clone
+
+ def new(self, data=None):
+ """Create a fresh SHA-256 hash object."""
+
+ return SHA256Hash(data)
+
+def new(data=None):
+ """Create a new hash object.
+
+ :parameter data:
+ Optional. The very first chunk of the message to hash.
+ It is equivalent to an early call to :meth:`SHA256Hash.update`.
+ :type data: byte string/byte array/memoryview
+
+ :Return: A :class:`SHA256Hash` hash object
+ """
+
+ return SHA256Hash().new(data)
+
+
+# The size of the resulting hash in bytes.
+digest_size = SHA256Hash.digest_size
+
+# The internal block size of the hash algorithm in bytes.
+block_size = SHA256Hash.block_size
+
+
+def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations):
+ """Compute the expensive inner loop in PBKDF-HMAC."""
+
+ assert iterations > 0
+
+ bfr = create_string_buffer(len(first_digest));
+ result = _raw_sha256_lib.SHA256_pbkdf2_hmac_assist(
+ inner._state.get(),
+ outer._state.get(),
+ first_digest,
+ bfr,
+ c_size_t(iterations),
+ c_size_t(len(first_digest)))
+
+ if result:
+ raise ValueError("Error %d with PBKDF2-HMAC assist for SHA256" % result)
+
+ return get_raw_buffer(bfr)
diff --git a/frozen_deps/Cryptodome/Hash/SHA256.pyi b/frozen_deps/Cryptodome/Hash/SHA256.pyi
new file mode 100644
index 0000000..cbf21bf
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHA256.pyi
@@ -0,0 +1,18 @@
+from typing import Union, Optional
+
+
+class SHA256Hash(object):
+ digest_size: int
+ block_size: int
+ oid: str
+ def __init__(self, data: Optional[Union[bytes, bytearray, memoryview]]=None) -> None: ...
+ def update(self, data: Union[bytes, bytearray, memoryview]) -> None: ...
+ def digest(self) -> bytes: ...
+ def hexdigest(self) -> str: ...
+ def copy(self) -> SHA256Hash: ...
+ def new(self, data: Optional[Union[bytes, bytearray, memoryview]]=None) -> SHA256Hash: ...
+
+def new(data: Optional[Union[bytes, bytearray, memoryview]]=None) -> SHA256Hash: ...
+
+digest_size: int
+block_size: int
diff --git a/frozen_deps/Cryptodome/Hash/SHA384.py b/frozen_deps/Cryptodome/Hash/SHA384.py
new file mode 100644
index 0000000..711aa73
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHA384.py
@@ -0,0 +1,186 @@
+# -*- 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 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_sha384_lib = load_pycryptodome_raw_lib("Cryptodome.Hash._SHA384",
+ """
+ int SHA384_init(void **shaState);
+ int SHA384_destroy(void *shaState);
+ int SHA384_update(void *hs,
+ const uint8_t *buf,
+ size_t len);
+ int SHA384_digest(const void *shaState,
+ uint8_t *digest,
+ size_t digest_size);
+ int SHA384_copy(const void *src, void *dst);
+
+ int SHA384_pbkdf2_hmac_assist(const void *inner,
+ const void *outer,
+ const uint8_t *first_digest,
+ uint8_t *final_digest,
+ size_t iterations,
+ size_t digest_size);
+ """)
+
+class SHA384Hash(object):
+ """A SHA-384 hash object.
+ Do not instantiate directly. Use the :func:`new` function.
+
+ :ivar oid: ASN.1 Object ID
+ :vartype oid: string
+
+ :ivar block_size: the size in bytes of the internal message block,
+ input to the compression function
+ :vartype block_size: integer
+
+ :ivar digest_size: the size in bytes of the resulting hash
+ :vartype digest_size: integer
+ """
+
+ # The size of the resulting hash in bytes.
+ digest_size = 48
+ # The internal block size of the hash algorithm in bytes.
+ block_size = 128
+ # ASN.1 Object ID
+ oid = '2.16.840.1.101.3.4.2.2'
+
+ def __init__(self, data=None):
+ state = VoidPointer()
+ result = _raw_sha384_lib.SHA384_init(state.address_of())
+ if result:
+ raise ValueError("Error %d while instantiating SHA384"
+ % result)
+ self._state = SmartPointer(state.get(),
+ _raw_sha384_lib.SHA384_destroy)
+ if data:
+ self.update(data)
+
+ def update(self, data):
+ """Continue hashing of a message by consuming the next chunk of data.
+
+ Args:
+ data (byte string/byte array/memoryview): The next chunk of the message being hashed.
+ """
+
+ result = _raw_sha384_lib.SHA384_update(self._state.get(),
+ c_uint8_ptr(data),
+ c_size_t(len(data)))
+ if result:
+ raise ValueError("Error %d while hashing data with SHA384"
+ % result)
+
+ def digest(self):
+ """Return the **binary** (non-printable) digest of the message that has been hashed so far.
+
+ :return: The hash digest, computed over the data processed so far.
+ Binary form.
+ :rtype: byte string
+ """
+
+ bfr = create_string_buffer(self.digest_size)
+ result = _raw_sha384_lib.SHA384_digest(self._state.get(),
+ bfr,
+ c_size_t(self.digest_size))
+ if result:
+ raise ValueError("Error %d while making SHA384 digest"
+ % result)
+
+ return get_raw_buffer(bfr)
+
+ def hexdigest(self):
+ """Return the **printable** digest of the message that has been hashed so far.
+
+ :return: The hash digest, computed over the data processed so far.
+ Hexadecimal encoded.
+ :rtype: string
+ """
+
+ return "".join(["%02x" % bord(x) for x in self.digest()])
+
+ def copy(self):
+ """Return a copy ("clone") of the hash object.
+
+ The copy will have the same internal state as the original hash
+ object.
+ This can be used to efficiently compute the digests of strings that
+ share a common initial substring.
+
+ :return: A hash object of the same type
+ """
+
+ clone = SHA384Hash()
+ result = _raw_sha384_lib.SHA384_copy(self._state.get(),
+ clone._state.get())
+ if result:
+ raise ValueError("Error %d while copying SHA384" % result)
+ return clone
+
+ def new(self, data=None):
+ """Create a fresh SHA-384 hash object."""
+
+ return SHA384Hash(data)
+
+
+def new(data=None):
+ """Create a new hash object.
+
+ :parameter data:
+ Optional. The very first chunk of the message to hash.
+ It is equivalent to an early call to :meth:`SHA384Hash.update`.
+ :type data: byte string/byte array/memoryview
+
+ :Return: A :class:`SHA384Hash` hash object
+ """
+
+ return SHA384Hash().new(data)
+
+
+# The size of the resulting hash in bytes.
+digest_size = SHA384Hash.digest_size
+
+# The internal block size of the hash algorithm in bytes.
+block_size = SHA384Hash.block_size
+
+
+def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations):
+ """Compute the expensive inner loop in PBKDF-HMAC."""
+
+ assert iterations > 0
+
+ bfr = create_string_buffer(len(first_digest));
+ result = _raw_sha384_lib.SHA384_pbkdf2_hmac_assist(
+ inner._state.get(),
+ outer._state.get(),
+ first_digest,
+ bfr,
+ c_size_t(iterations),
+ c_size_t(len(first_digest)))
+
+ if result:
+ raise ValueError("Error %d with PBKDF2-HMAC assist for SHA384" % result)
+
+ return get_raw_buffer(bfr)
diff --git a/frozen_deps/Cryptodome/Hash/SHA384.pyi b/frozen_deps/Cryptodome/Hash/SHA384.pyi
new file mode 100644
index 0000000..c2aab9e
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHA384.pyi
@@ -0,0 +1,19 @@
+from typing import Union, Optional
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class SHA384Hash(object):
+ digest_size: int
+ block_size: int
+ oid: str
+
+ def __init__(self, data: Optional[Buffer] = ...) -> None: ...
+ def update(self, data: Buffer) -> None: ...
+ def digest(self) -> bytes: ...
+ def hexdigest(self) -> str: ...
+ def copy(self) -> SHA384Hash: ...
+ def new(self, data: Optional[Buffer] = ...) -> SHA384Hash: ...
+
+def new(data: Optional[Buffer] = ...) -> SHA384Hash: ...
+digest_size: int
+block_size: int
diff --git a/frozen_deps/Cryptodome/Hash/SHA3_224.py b/frozen_deps/Cryptodome/Hash/SHA3_224.py
new file mode 100644
index 0000000..3196bd6
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHA3_224.py
@@ -0,0 +1,147 @@
+# -*- 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 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)
+
+from Cryptodome.Hash.keccak import _raw_keccak_lib
+
+class SHA3_224_Hash(object):
+ """A SHA3-224 hash object.
+ Do not instantiate directly.
+ Use the :func:`new` function.
+
+ :ivar oid: ASN.1 Object ID
+ :vartype oid: string
+
+ :ivar digest_size: the size in bytes of the resulting hash
+ :vartype digest_size: integer
+ """
+
+ # The size of the resulting hash in bytes.
+ digest_size = 28
+
+ # ASN.1 Object ID
+ oid = "2.16.840.1.101.3.4.2.7"
+
+ def __init__(self, data, update_after_digest):
+ self._update_after_digest = update_after_digest
+ self._digest_done = False
+
+ state = VoidPointer()
+ result = _raw_keccak_lib.keccak_init(state.address_of(),
+ c_size_t(self.digest_size * 2),
+ 0x06)
+ if result:
+ raise ValueError("Error %d while instantiating SHA-3/224"
+ % result)
+ self._state = SmartPointer(state.get(),
+ _raw_keccak_lib.keccak_destroy)
+ if data:
+ self.update(data)
+
+ def update(self, data):
+ """Continue hashing of a message by consuming the next chunk of data.
+
+ Args:
+ data (byte string/byte array/memoryview): The next chunk of the message being hashed.
+ """
+
+ if self._digest_done and not self._update_after_digest:
+ raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
+
+ result = _raw_keccak_lib.keccak_absorb(self._state.get(),
+ c_uint8_ptr(data),
+ c_size_t(len(data)))
+ if result:
+ raise ValueError("Error %d while updating SHA-3/224"
+ % result)
+ return self
+
+ def digest(self):
+ """Return the **binary** (non-printable) digest of the message that has been hashed so far.
+
+ :return: The hash digest, computed over the data processed so far.
+ Binary form.
+ :rtype: byte string
+ """
+
+ self._digest_done = True
+
+ bfr = create_string_buffer(self.digest_size)
+ result = _raw_keccak_lib.keccak_digest(self._state.get(),
+ bfr,
+ c_size_t(self.digest_size))
+ if result:
+ raise ValueError("Error %d while instantiating SHA-3/224"
+ % result)
+
+ self._digest_value = get_raw_buffer(bfr)
+ return self._digest_value
+
+ def hexdigest(self):
+ """Return the **printable** digest of the message that has been hashed so far.
+
+ :return: The hash digest, computed over the data processed so far.
+ Hexadecimal encoded.
+ :rtype: string
+ """
+
+ return "".join(["%02x" % bord(x) for x in self.digest()])
+
+ def new(self):
+ """Create a fresh SHA3-224 hash object."""
+
+ return type(self)(None, self._update_after_digest)
+
+
+def new(*args, **kwargs):
+ """Create a new hash object.
+
+ Args:
+ data (byte string/byte array/memoryview):
+ The very first chunk of the message to hash.
+ It is equivalent to an early call to :meth:`update`.
+ update_after_digest (boolean):
+ Whether :meth:`digest` can be followed by another :meth:`update`
+ (default: ``False``).
+
+ :Return: A :class:`SHA3_224_Hash` hash object
+ """
+
+ data = kwargs.pop("data", None)
+ update_after_digest = kwargs.pop("update_after_digest", False)
+ if len(args) == 1:
+ if data:
+ raise ValueError("Initial data for hash specified twice")
+ data = args[0]
+
+ if kwargs:
+ raise TypeError("Unknown parameters: " + str(kwargs))
+
+ return SHA3_224_Hash(data, update_after_digest)
+
+# The size of the resulting hash in bytes.
+digest_size = SHA3_224_Hash.digest_size
diff --git a/frozen_deps/Cryptodome/Hash/SHA3_224.pyi b/frozen_deps/Cryptodome/Hash/SHA3_224.pyi
new file mode 100644
index 0000000..3437042
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHA3_224.pyi
@@ -0,0 +1,16 @@
+from typing import Union, Optional
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class SHA3_224_Hash(object):
+ digest_size: int
+ oid: str
+ def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ...
+ def update(self, data: Buffer) -> SHA3_224_Hash: ...
+ def digest(self) -> bytes: ...
+ def hexdigest(self) -> str: ...
+ def new(self) -> SHA3_224_Hash: ...
+
+def new(__data: Buffer = ..., update_after_digest: bool = ...) -> SHA3_224_Hash: ...
+
+digest_size: int
diff --git a/frozen_deps/Cryptodome/Hash/SHA3_256.py b/frozen_deps/Cryptodome/Hash/SHA3_256.py
new file mode 100644
index 0000000..89e3b42
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHA3_256.py
@@ -0,0 +1,147 @@
+# -*- 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 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)
+
+from Cryptodome.Hash.keccak import _raw_keccak_lib
+
+class SHA3_256_Hash(object):
+ """A SHA3-256 hash object.
+ Do not instantiate directly.
+ Use the :func:`new` function.
+
+ :ivar oid: ASN.1 Object ID
+ :vartype oid: string
+
+ :ivar digest_size: the size in bytes of the resulting hash
+ :vartype digest_size: integer
+ """
+
+ # The size of the resulting hash in bytes.
+ digest_size = 32
+
+ # ASN.1 Object ID
+ oid = "2.16.840.1.101.3.4.2.8"
+
+ def __init__(self, data, update_after_digest):
+ self._update_after_digest = update_after_digest
+ self._digest_done = False
+
+ state = VoidPointer()
+ result = _raw_keccak_lib.keccak_init(state.address_of(),
+ c_size_t(self.digest_size * 2),
+ 0x06)
+ if result:
+ raise ValueError("Error %d while instantiating SHA-3/256"
+ % result)
+ self._state = SmartPointer(state.get(),
+ _raw_keccak_lib.keccak_destroy)
+ if data:
+ self.update(data)
+
+ def update(self, data):
+ """Continue hashing of a message by consuming the next chunk of data.
+
+ Args:
+ data (byte string/byte array/memoryview): The next chunk of the message being hashed.
+ """
+
+ if self._digest_done and not self._update_after_digest:
+ raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
+
+ result = _raw_keccak_lib.keccak_absorb(self._state.get(),
+ c_uint8_ptr(data),
+ c_size_t(len(data)))
+ if result:
+ raise ValueError("Error %d while updating SHA-3/256"
+ % result)
+ return self
+
+ def digest(self):
+ """Return the **binary** (non-printable) digest of the message that has been hashed so far.
+
+ :return: The hash digest, computed over the data processed so far.
+ Binary form.
+ :rtype: byte string
+ """
+
+ self._digest_done = True
+
+ bfr = create_string_buffer(self.digest_size)
+ result = _raw_keccak_lib.keccak_digest(self._state.get(),
+ bfr,
+ c_size_t(self.digest_size))
+ if result:
+ raise ValueError("Error %d while instantiating SHA-3/256"
+ % result)
+
+ self._digest_value = get_raw_buffer(bfr)
+ return self._digest_value
+
+ def hexdigest(self):
+ """Return the **printable** digest of the message that has been hashed so far.
+
+ :return: The hash digest, computed over the data processed so far.
+ Hexadecimal encoded.
+ :rtype: string
+ """
+
+ return "".join(["%02x" % bord(x) for x in self.digest()])
+
+ def new(self):
+ """Create a fresh SHA3-256 hash object."""
+
+ return type(self)(None, self._update_after_digest)
+
+
+def new(*args, **kwargs):
+ """Create a new hash object.
+
+ Args:
+ data (byte string/byte array/memoryview):
+ The very first chunk of the message to hash.
+ It is equivalent to an early call to :meth:`update`.
+ update_after_digest (boolean):
+ Whether :meth:`digest` can be followed by another :meth:`update`
+ (default: ``False``).
+
+ :Return: A :class:`SHA3_256_Hash` hash object
+ """
+
+ data = kwargs.pop("data", None)
+ update_after_digest = kwargs.pop("update_after_digest", False)
+ if len(args) == 1:
+ if data:
+ raise ValueError("Initial data for hash specified twice")
+ data = args[0]
+
+ if kwargs:
+ raise TypeError("Unknown parameters: " + str(kwargs))
+
+ return SHA3_256_Hash(data, update_after_digest)
+
+# The size of the resulting hash in bytes.
+digest_size = SHA3_256_Hash.digest_size
diff --git a/frozen_deps/Cryptodome/Hash/SHA3_256.pyi b/frozen_deps/Cryptodome/Hash/SHA3_256.pyi
new file mode 100644
index 0000000..c1a07fa
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHA3_256.pyi
@@ -0,0 +1,16 @@
+from typing import Union, Optional
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class SHA3_256_Hash(object):
+ digest_size: int
+ oid: str
+ def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ...
+ def update(self, data: Buffer) -> SHA3_256_Hash: ...
+ def digest(self) -> bytes: ...
+ def hexdigest(self) -> str: ...
+ def new(self) -> SHA3_256_Hash: ...
+
+def new(__data: Buffer = ..., update_after_digest: bool = ...) -> SHA3_256_Hash: ...
+
+digest_size: int
diff --git a/frozen_deps/Cryptodome/Hash/SHA3_384.py b/frozen_deps/Cryptodome/Hash/SHA3_384.py
new file mode 100644
index 0000000..e6baf3f
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHA3_384.py
@@ -0,0 +1,147 @@
+# -*- 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 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)
+
+from Cryptodome.Hash.keccak import _raw_keccak_lib
+
+class SHA3_384_Hash(object):
+ """A SHA3-384 hash object.
+ Do not instantiate directly.
+ Use the :func:`new` function.
+
+ :ivar oid: ASN.1 Object ID
+ :vartype oid: string
+
+ :ivar digest_size: the size in bytes of the resulting hash
+ :vartype digest_size: integer
+ """
+
+ # The size of the resulting hash in bytes.
+ digest_size = 48
+
+ # ASN.1 Object ID
+ oid = "2.16.840.1.101.3.4.2.9"
+
+ def __init__(self, data, update_after_digest):
+ self._update_after_digest = update_after_digest
+ self._digest_done = False
+
+ state = VoidPointer()
+ result = _raw_keccak_lib.keccak_init(state.address_of(),
+ c_size_t(self.digest_size * 2),
+ 0x06)
+ if result:
+ raise ValueError("Error %d while instantiating SHA-3/384"
+ % result)
+ self._state = SmartPointer(state.get(),
+ _raw_keccak_lib.keccak_destroy)
+ if data:
+ self.update(data)
+
+ def update(self, data):
+ """Continue hashing of a message by consuming the next chunk of data.
+
+ Args:
+ data (byte string/byte array/memoryview): The next chunk of the message being hashed.
+ """
+
+ if self._digest_done and not self._update_after_digest:
+ raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
+
+ result = _raw_keccak_lib.keccak_absorb(self._state.get(),
+ c_uint8_ptr(data),
+ c_size_t(len(data)))
+ if result:
+ raise ValueError("Error %d while updating SHA-3/384"
+ % result)
+ return self
+
+ def digest(self):
+ """Return the **binary** (non-printable) digest of the message that has been hashed so far.
+
+ :return: The hash digest, computed over the data processed so far.
+ Binary form.
+ :rtype: byte string
+ """
+
+ self._digest_done = True
+
+ bfr = create_string_buffer(self.digest_size)
+ result = _raw_keccak_lib.keccak_digest(self._state.get(),
+ bfr,
+ c_size_t(self.digest_size))
+ if result:
+ raise ValueError("Error %d while instantiating SHA-3/384"
+ % result)
+
+ self._digest_value = get_raw_buffer(bfr)
+ return self._digest_value
+
+ def hexdigest(self):
+ """Return the **printable** digest of the message that has been hashed so far.
+
+ :return: The hash digest, computed over the data processed so far.
+ Hexadecimal encoded.
+ :rtype: string
+ """
+
+ return "".join(["%02x" % bord(x) for x in self.digest()])
+
+ def new(self):
+ """Create a fresh SHA3-384 hash object."""
+
+ return type(self)(None, self._update_after_digest)
+
+
+def new(*args, **kwargs):
+ """Create a new hash object.
+
+ Args:
+ data (byte string/byte array/memoryview):
+ The very first chunk of the message to hash.
+ It is equivalent to an early call to :meth:`update`.
+ update_after_digest (boolean):
+ Whether :meth:`digest` can be followed by another :meth:`update`
+ (default: ``False``).
+
+ :Return: A :class:`SHA3_384_Hash` hash object
+ """
+
+ data = kwargs.pop("data", None)
+ update_after_digest = kwargs.pop("update_after_digest", False)
+ if len(args) == 1:
+ if data:
+ raise ValueError("Initial data for hash specified twice")
+ data = args[0]
+
+ if kwargs:
+ raise TypeError("Unknown parameters: " + str(kwargs))
+
+ return SHA3_384_Hash(data, update_after_digest)
+
+# The size of the resulting hash in bytes.
+digest_size = SHA3_384_Hash.digest_size
diff --git a/frozen_deps/Cryptodome/Hash/SHA3_384.pyi b/frozen_deps/Cryptodome/Hash/SHA3_384.pyi
new file mode 100644
index 0000000..d029ab6
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHA3_384.pyi
@@ -0,0 +1,16 @@
+from typing import Union, Optional
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class SHA3_384_Hash(object):
+ digest_size: int
+ oid: str
+ def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ...
+ def update(self, data: Buffer) -> SHA3_384_Hash: ...
+ def digest(self) -> bytes: ...
+ def hexdigest(self) -> str: ...
+ def new(self) -> SHA3_384_Hash: ...
+
+def new(__data: Buffer = ..., update_after_digest: bool = ...) -> SHA3_384_Hash: ...
+
+digest_size: int
diff --git a/frozen_deps/Cryptodome/Hash/SHA3_512.py b/frozen_deps/Cryptodome/Hash/SHA3_512.py
new file mode 100644
index 0000000..676ce2f
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHA3_512.py
@@ -0,0 +1,148 @@
+# -*- 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 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)
+
+from Cryptodome.Hash.keccak import _raw_keccak_lib
+
+class SHA3_512_Hash(object):
+ """A SHA3-512 hash object.
+ Do not instantiate directly.
+ Use the :func:`new` function.
+
+ :ivar oid: ASN.1 Object ID
+ :vartype oid: string
+
+ :ivar digest_size: the size in bytes of the resulting hash
+ :vartype digest_size: integer
+ """
+
+ # The size of the resulting hash in bytes.
+ digest_size = 64
+
+ # ASN.1 Object ID
+ oid = "2.16.840.1.101.3.4.2.10"
+
+ def __init__(self, data, update_after_digest):
+ self._update_after_digest = update_after_digest
+ self._digest_done = False
+
+ state = VoidPointer()
+ result = _raw_keccak_lib.keccak_init(state.address_of(),
+ c_size_t(self.digest_size * 2),
+ 0x06)
+ if result:
+ raise ValueError("Error %d while instantiating SHA-3/512"
+ % result)
+ self._state = SmartPointer(state.get(),
+ _raw_keccak_lib.keccak_destroy)
+ if data:
+ self.update(data)
+
+ def update(self, data):
+ """Continue hashing of a message by consuming the next chunk of data.
+
+ Args:
+ data (byte string/byte array/memoryview): The next chunk of the message being hashed.
+ """
+
+ if self._digest_done and not self._update_after_digest:
+ raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
+
+ result = _raw_keccak_lib.keccak_absorb(self._state.get(),
+ c_uint8_ptr(data),
+ c_size_t(len(data)))
+ if result:
+ raise ValueError("Error %d while updating SHA-3/512"
+ % result)
+ return self
+
+ def digest(self):
+
+ """Return the **binary** (non-printable) digest of the message that has been hashed so far.
+
+ :return: The hash digest, computed over the data processed so far.
+ Binary form.
+ :rtype: byte string
+ """
+
+ self._digest_done = True
+
+ bfr = create_string_buffer(self.digest_size)
+ result = _raw_keccak_lib.keccak_digest(self._state.get(),
+ bfr,
+ c_size_t(self.digest_size))
+ if result:
+ raise ValueError("Error %d while instantiating SHA-3/512"
+ % result)
+
+ self._digest_value = get_raw_buffer(bfr)
+ return self._digest_value
+
+ def hexdigest(self):
+ """Return the **printable** digest of the message that has been hashed so far.
+
+ :return: The hash digest, computed over the data processed so far.
+ Hexadecimal encoded.
+ :rtype: string
+ """
+
+ return "".join(["%02x" % bord(x) for x in self.digest()])
+
+ def new(self):
+ """Create a fresh SHA3-512 hash object."""
+
+ return type(self)(None, self._update_after_digest)
+
+
+def new(*args, **kwargs):
+ """Create a new hash object.
+
+ Args:
+ data (byte string/byte array/memoryview):
+ The very first chunk of the message to hash.
+ It is equivalent to an early call to :meth:`update`.
+ update_after_digest (boolean):
+ Whether :meth:`digest` can be followed by another :meth:`update`
+ (default: ``False``).
+
+ :Return: A :class:`SHA3_512_Hash` hash object
+ """
+
+ data = kwargs.pop("data", None)
+ update_after_digest = kwargs.pop("update_after_digest", False)
+ if len(args) == 1:
+ if data:
+ raise ValueError("Initial data for hash specified twice")
+ data = args[0]
+
+ if kwargs:
+ raise TypeError("Unknown parameters: " + str(kwargs))
+
+ return SHA3_512_Hash(data, update_after_digest)
+
+# The size of the resulting hash in bytes.
+digest_size = SHA3_512_Hash.digest_size
diff --git a/frozen_deps/Cryptodome/Hash/SHA3_512.pyi b/frozen_deps/Cryptodome/Hash/SHA3_512.pyi
new file mode 100644
index 0000000..2c5403b
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHA3_512.pyi
@@ -0,0 +1,16 @@
+from typing import Union, Optional
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class SHA3_512_Hash(object):
+ digest_size: int
+ oid: str
+ def __init__(self, data: Optional[Buffer], update_after_digest: bool) -> None: ...
+ def update(self, data: Buffer) -> SHA3_512_Hash: ...
+ def digest(self) -> bytes: ...
+ def hexdigest(self) -> str: ...
+ def new(self) -> SHA3_512_Hash: ...
+
+def new(__data: Buffer = ..., update_after_digest: bool = ...) -> SHA3_512_Hash: ...
+
+digest_size: int
diff --git a/frozen_deps/Cryptodome/Hash/SHA512.py b/frozen_deps/Cryptodome/Hash/SHA512.py
new file mode 100644
index 0000000..5066197
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHA512.py
@@ -0,0 +1,204 @@
+# -*- 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 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_sha512_lib = load_pycryptodome_raw_lib("Cryptodome.Hash._SHA512",
+ """
+ int SHA512_init(void **shaState,
+ size_t digest_size);
+ int SHA512_destroy(void *shaState);
+ int SHA512_update(void *hs,
+ const uint8_t *buf,
+ size_t len);
+ int SHA512_digest(const void *shaState,
+ uint8_t *digest,
+ size_t digest_size);
+ int SHA512_copy(const void *src, void *dst);
+
+ int SHA512_pbkdf2_hmac_assist(const void *inner,
+ const void *outer,
+ const uint8_t *first_digest,
+ uint8_t *final_digest,
+ size_t iterations,
+ size_t digest_size);
+ """)
+
+class SHA512Hash(object):
+ """A SHA-512 hash object (possibly in its truncated version SHA-512/224 or
+ SHA-512/256.
+ Do not instantiate directly. Use the :func:`new` function.
+
+ :ivar oid: ASN.1 Object ID
+ :vartype oid: string
+
+ :ivar block_size: the size in bytes of the internal message block,
+ input to the compression function
+ :vartype block_size: integer
+
+ :ivar digest_size: the size in bytes of the resulting hash
+ :vartype digest_size: integer
+ """
+
+ # The internal block size of the hash algorithm in bytes.
+ block_size = 128
+
+ def __init__(self, data, truncate):
+ self._truncate = truncate
+
+ if truncate is None:
+ self.oid = "2.16.840.1.101.3.4.2.3"
+ self.digest_size = 64
+ elif truncate == "224":
+ self.oid = "2.16.840.1.101.3.4.2.5"
+ self.digest_size = 28
+ elif truncate == "256":
+ self.oid = "2.16.840.1.101.3.4.2.6"
+ self.digest_size = 32
+ else:
+ raise ValueError("Incorrect truncation length. It must be '224' or '256'.")
+
+ state = VoidPointer()
+ result = _raw_sha512_lib.SHA512_init(state.address_of(),
+ c_size_t(self.digest_size))
+ if result:
+ raise ValueError("Error %d while instantiating SHA-512"
+ % result)
+ self._state = SmartPointer(state.get(),
+ _raw_sha512_lib.SHA512_destroy)
+ if data:
+ self.update(data)
+
+ def update(self, data):
+ """Continue hashing of a message by consuming the next chunk of data.
+
+ Args:
+ data (byte string/byte array/memoryview): The next chunk of the message being hashed.
+ """
+
+ result = _raw_sha512_lib.SHA512_update(self._state.get(),
+ c_uint8_ptr(data),
+ c_size_t(len(data)))
+ if result:
+ raise ValueError("Error %d while hashing data with SHA512"
+ % result)
+
+ def digest(self):
+ """Return the **binary** (non-printable) digest of the message that has been hashed so far.
+
+ :return: The hash digest, computed over the data processed so far.
+ Binary form.
+ :rtype: byte string
+ """
+
+ bfr = create_string_buffer(self.digest_size)
+ result = _raw_sha512_lib.SHA512_digest(self._state.get(),
+ bfr,
+ c_size_t(self.digest_size))
+ if result:
+ raise ValueError("Error %d while making SHA512 digest"
+ % result)
+
+ return get_raw_buffer(bfr)
+
+ def hexdigest(self):
+ """Return the **printable** digest of the message that has been hashed so far.
+
+ :return: The hash digest, computed over the data processed so far.
+ Hexadecimal encoded.
+ :rtype: string
+ """
+
+ return "".join(["%02x" % bord(x) for x in self.digest()])
+
+ def copy(self):
+ """Return a copy ("clone") of the hash object.
+
+ The copy will have the same internal state as the original hash
+ object.
+ This can be used to efficiently compute the digests of strings that
+ share a common initial substring.
+
+ :return: A hash object of the same type
+ """
+
+ clone = SHA512Hash(None, self._truncate)
+ result = _raw_sha512_lib.SHA512_copy(self._state.get(),
+ clone._state.get())
+ if result:
+ raise ValueError("Error %d while copying SHA512" % result)
+ return clone
+
+ def new(self, data=None):
+ """Create a fresh SHA-512 hash object."""
+
+ return SHA512Hash(data, self._truncate)
+
+
+def new(data=None, truncate=None):
+ """Create a new hash object.
+
+ Args:
+ data (bytes/bytearray/memoryview):
+ Optional. The very first chunk of the message to hash.
+ It is equivalent to an early call to :meth:`SHA512Hash.update`.
+ truncate (string):
+ Optional. The desired length of the digest. It can be either "224" or
+ "256". If not present, the digest is 512 bits long.
+ Passing this parameter is **not** equivalent to simply truncating
+ the output digest.
+
+ :Return: A :class:`SHA512Hash` hash object
+ """
+
+ return SHA512Hash(data, truncate)
+
+
+# The size of the full SHA-512 hash in bytes.
+digest_size = 64
+
+# The internal block size of the hash algorithm in bytes.
+block_size = 128
+
+
+def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations):
+ """Compute the expensive inner loop in PBKDF-HMAC."""
+
+ assert iterations > 0
+
+ bfr = create_string_buffer(len(first_digest));
+ result = _raw_sha512_lib.SHA512_pbkdf2_hmac_assist(
+ inner._state.get(),
+ outer._state.get(),
+ first_digest,
+ bfr,
+ c_size_t(iterations),
+ c_size_t(len(first_digest)))
+
+ if result:
+ raise ValueError("Error %d with PBKDF2-HMAC assist for SHA512" % result)
+
+ return get_raw_buffer(bfr)
diff --git a/frozen_deps/Cryptodome/Hash/SHA512.pyi b/frozen_deps/Cryptodome/Hash/SHA512.pyi
new file mode 100644
index 0000000..f219ee9
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHA512.pyi
@@ -0,0 +1,22 @@
+from typing import Union, Optional
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class SHA512Hash(object):
+ digest_size: int
+ block_size: int
+ oid: str
+
+ def __init__(self,
+ data: Optional[Buffer],
+ truncate: Optional[str]) -> None: ...
+ def update(self, data: Buffer) -> None: ...
+ def digest(self) -> bytes: ...
+ def hexdigest(self) -> str: ...
+ def copy(self) -> SHA512Hash: ...
+ def new(self, data: Optional[Buffer] = ...) -> SHA512Hash: ...
+
+def new(data: Optional[Buffer] = ...,
+ truncate: Optional[str] = ...) -> SHA512Hash: ...
+digest_size: int
+block_size: int
diff --git a/frozen_deps/Cryptodome/Hash/SHAKE128.py b/frozen_deps/Cryptodome/Hash/SHAKE128.py
new file mode 100644
index 0000000..be2b22e
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHAKE128.py
@@ -0,0 +1,127 @@
+# ===================================================================
+#
+# Copyright (c) 2015, Legrandin <[email protected]>
+# 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)
+
+from Cryptodome.Hash.keccak import _raw_keccak_lib
+
+class SHAKE128_XOF(object):
+ """A SHAKE128 hash object.
+ Do not instantiate directly.
+ Use the :func:`new` function.
+
+ :ivar oid: ASN.1 Object ID
+ :vartype oid: string
+ """
+
+ # ASN.1 Object ID
+ oid = "2.16.840.1.101.3.4.2.11"
+
+ def __init__(self, data=None):
+ state = VoidPointer()
+ result = _raw_keccak_lib.keccak_init(state.address_of(),
+ c_size_t(32),
+ 0x1F)
+ if result:
+ raise ValueError("Error %d while instantiating SHAKE128"
+ % result)
+ self._state = SmartPointer(state.get(),
+ _raw_keccak_lib.keccak_destroy)
+ self._is_squeezing = False
+ if data:
+ self.update(data)
+
+ def update(self, data):
+ """Continue hashing of a message by consuming the next chunk of data.
+
+ Args:
+ data (byte string/byte array/memoryview): The next chunk of the message being hashed.
+ """
+
+ if self._is_squeezing:
+ raise TypeError("You cannot call 'update' after the first 'read'")
+
+ result = _raw_keccak_lib.keccak_absorb(self._state.get(),
+ c_uint8_ptr(data),
+ c_size_t(len(data)))
+ if result:
+ raise ValueError("Error %d while updating SHAKE128 state"
+ % result)
+ return self
+
+ def read(self, length):
+ """
+ Compute the next piece of XOF output.
+
+ .. note::
+ You cannot use :meth:`update` anymore after the first call to
+ :meth:`read`.
+
+ Args:
+ length (integer): the amount of bytes this method must return
+
+ :return: the next piece of XOF output (of the given length)
+ :rtype: byte string
+ """
+
+ self._is_squeezing = True
+ bfr = create_string_buffer(length)
+ result = _raw_keccak_lib.keccak_squeeze(self._state.get(),
+ bfr,
+ c_size_t(length))
+ if result:
+ raise ValueError("Error %d while extracting from SHAKE128"
+ % result)
+
+ return get_raw_buffer(bfr)
+
+ def new(self, data=None):
+ return type(self)(data=data)
+
+
+def new(data=None):
+ """Return a fresh instance of a SHAKE128 object.
+
+ Args:
+ data (bytes/bytearray/memoryview):
+ The very first chunk of the message to hash.
+ It is equivalent to an early call to :meth:`update`.
+ Optional.
+
+ :Return: A :class:`SHAKE128_XOF` object
+ """
+
+ return SHAKE128_XOF(data=data)
diff --git a/frozen_deps/Cryptodome/Hash/SHAKE128.pyi b/frozen_deps/Cryptodome/Hash/SHAKE128.pyi
new file mode 100644
index 0000000..f618881
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHAKE128.pyi
@@ -0,0 +1,13 @@
+from typing import Union, Optional
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class SHAKE128_XOF(object):
+ oid: str
+ def __init__(self,
+ data: Optional[Buffer] = ...) -> None: ...
+ def update(self, data: Buffer) -> SHAKE128_XOF: ...
+ def read(self, length: int) -> bytes: ...
+ def new(self, data: Optional[Buffer] = ...) -> SHAKE128_XOF: ...
+
+def new(data: Optional[Buffer] = ...) -> SHAKE128_XOF: ...
diff --git a/frozen_deps/Cryptodome/Hash/SHAKE256.py b/frozen_deps/Cryptodome/Hash/SHAKE256.py
new file mode 100644
index 0000000..46040e1
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHAKE256.py
@@ -0,0 +1,127 @@
+# ===================================================================
+#
+# Copyright (c) 2015, Legrandin <[email protected]>
+# 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)
+
+from Cryptodome.Hash.keccak import _raw_keccak_lib
+
+class SHAKE256_XOF(object):
+ """A SHAKE256 hash object.
+ Do not instantiate directly.
+ Use the :func:`new` function.
+
+ :ivar oid: ASN.1 Object ID
+ :vartype oid: string
+ """
+
+ # ASN.1 Object ID
+ oid = "2.16.840.1.101.3.4.2.12"
+
+ def __init__(self, data=None):
+ state = VoidPointer()
+ result = _raw_keccak_lib.keccak_init(state.address_of(),
+ c_size_t(64),
+ 0x1F)
+ if result:
+ raise ValueError("Error %d while instantiating SHAKE256"
+ % result)
+ self._state = SmartPointer(state.get(),
+ _raw_keccak_lib.keccak_destroy)
+ self._is_squeezing = False
+ if data:
+ self.update(data)
+
+ def update(self, data):
+ """Continue hashing of a message by consuming the next chunk of data.
+
+ Args:
+ data (byte string/byte array/memoryview): The next chunk of the message being hashed.
+ """
+
+ if self._is_squeezing:
+ raise TypeError("You cannot call 'update' after the first 'read'")
+
+ result = _raw_keccak_lib.keccak_absorb(self._state.get(),
+ c_uint8_ptr(data),
+ c_size_t(len(data)))
+ if result:
+ raise ValueError("Error %d while updating SHAKE256 state"
+ % result)
+ return self
+
+ def read(self, length):
+ """
+ Compute the next piece of XOF output.
+
+ .. note::
+ You cannot use :meth:`update` anymore after the first call to
+ :meth:`read`.
+
+ Args:
+ length (integer): the amount of bytes this method must return
+
+ :return: the next piece of XOF output (of the given length)
+ :rtype: byte string
+ """
+
+ self._is_squeezing = True
+ bfr = create_string_buffer(length)
+ result = _raw_keccak_lib.keccak_squeeze(self._state.get(),
+ bfr,
+ c_size_t(length))
+ if result:
+ raise ValueError("Error %d while extracting from SHAKE256"
+ % result)
+
+ return get_raw_buffer(bfr)
+
+ def new(self, data=None):
+ return type(self)(data=data)
+
+
+def new(data=None):
+ """Return a fresh instance of a SHAKE256 object.
+
+ Args:
+ data (bytes/bytearray/memoryview):
+ The very first chunk of the message to hash.
+ It is equivalent to an early call to :meth:`update`.
+ Optional.
+
+ :Return: A :class:`SHAKE256_XOF` object
+ """
+
+ return SHAKE256_XOF(data=data)
diff --git a/frozen_deps/Cryptodome/Hash/SHAKE256.pyi b/frozen_deps/Cryptodome/Hash/SHAKE256.pyi
new file mode 100644
index 0000000..029347a
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/SHAKE256.pyi
@@ -0,0 +1,13 @@
+from typing import Union, Optional
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class SHAKE256_XOF(object):
+ oid: str
+ def __init__(self,
+ data: Optional[Buffer] = ...) -> None: ...
+ def update(self, data: Buffer) -> SHAKE256_XOF: ...
+ def read(self, length: int) -> bytes: ...
+ def new(self, data: Optional[Buffer] = ...) -> SHAKE256_XOF: ...
+
+def new(data: Optional[Buffer] = ...) -> SHAKE256_XOF: ...
diff --git a/frozen_deps/Cryptodome/Hash/_BLAKE2b.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Hash/_BLAKE2b.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..35ee701
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/_BLAKE2b.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Hash/_BLAKE2s.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Hash/_BLAKE2s.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..7f391c9
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/_BLAKE2s.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Hash/_MD2.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Hash/_MD2.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..8fffa21
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/_MD2.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Hash/_MD4.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Hash/_MD4.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..12b4c06
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/_MD4.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Hash/_MD5.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Hash/_MD5.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..6fb6942
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/_MD5.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Hash/_RIPEMD160.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Hash/_RIPEMD160.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..2d8928d
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/_RIPEMD160.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Hash/_SHA1.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Hash/_SHA1.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..7324a29
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/_SHA1.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Hash/_SHA224.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Hash/_SHA224.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..c60f2ae
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/_SHA224.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Hash/_SHA256.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Hash/_SHA256.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..0b8212d
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/_SHA256.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Hash/_SHA384.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Hash/_SHA384.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..b3ef7ab
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/_SHA384.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Hash/_SHA512.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Hash/_SHA512.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..424a00b
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/_SHA512.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Hash/__init__.py b/frozen_deps/Cryptodome/Hash/__init__.py
new file mode 100644
index 0000000..719cd8d
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/__init__.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+__all__ = ['HMAC', 'MD2', 'MD4', 'MD5', 'RIPEMD160', 'SHA1',
+ 'SHA224', 'SHA256', 'SHA384', 'SHA512', 'CMAC', 'Poly1305']
diff --git a/frozen_deps/Cryptodome/Hash/__init__.pyi b/frozen_deps/Cryptodome/Hash/__init__.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/__init__.pyi
diff --git a/frozen_deps/Cryptodome/Hash/_ghash_clmul.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Hash/_ghash_clmul.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..c4387d7
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/_ghash_clmul.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Hash/_ghash_portable.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Hash/_ghash_portable.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..ed1479f
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/_ghash_portable.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Hash/_keccak.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Hash/_keccak.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..074d7c4
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/_keccak.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Hash/_poly1305.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Hash/_poly1305.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..b9ae83f
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/_poly1305.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Hash/keccak.py b/frozen_deps/Cryptodome/Hash/keccak.py
new file mode 100644
index 0000000..9ae8ec5
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/keccak.py
@@ -0,0 +1,173 @@
+# ===================================================================
+#
+# Copyright (c) 2015, Legrandin <[email protected]>
+# 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_keccak_lib = load_pycryptodome_raw_lib("Cryptodome.Hash._keccak",
+ """
+ int keccak_init(void **state,
+ size_t capacity_bytes,
+ uint8_t padding_byte);
+ int keccak_destroy(void *state);
+ int keccak_absorb(void *state,
+ const uint8_t *in,
+ size_t len);
+ int keccak_squeeze(const void *state,
+ uint8_t *out,
+ size_t len);
+ int keccak_digest(void *state, uint8_t *digest, size_t len);
+ """)
+
+class Keccak_Hash(object):
+ """A Keccak hash object.
+ Do not instantiate directly.
+ Use the :func:`new` function.
+
+ :ivar digest_size: the size in bytes of the resulting hash
+ :vartype digest_size: integer
+ """
+
+ def __init__(self, data, digest_bytes, update_after_digest):
+ # The size of the resulting hash in bytes.
+ self.digest_size = digest_bytes
+
+ self._update_after_digest = update_after_digest
+ self._digest_done = False
+
+ state = VoidPointer()
+ result = _raw_keccak_lib.keccak_init(state.address_of(),
+ c_size_t(self.digest_size * 2),
+ 0x01)
+ if result:
+ raise ValueError("Error %d while instantiating keccak" % result)
+ self._state = SmartPointer(state.get(),
+ _raw_keccak_lib.keccak_destroy)
+ if data:
+ self.update(data)
+
+ def update(self, data):
+ """Continue hashing of a message by consuming the next chunk of data.
+
+ Args:
+ data (byte string/byte array/memoryview): The next chunk of the message being hashed.
+ """
+
+ if self._digest_done and not self._update_after_digest:
+ raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
+
+ result = _raw_keccak_lib.keccak_absorb(self._state.get(),
+ c_uint8_ptr(data),
+ c_size_t(len(data)))
+ if result:
+ raise ValueError("Error %d while updating keccak" % result)
+ return self
+
+ def digest(self):
+ """Return the **binary** (non-printable) digest of the message that has been hashed so far.
+
+ :return: The hash digest, computed over the data processed so far.
+ Binary form.
+ :rtype: byte string
+ """
+
+ self._digest_done = True
+ bfr = create_string_buffer(self.digest_size)
+ result = _raw_keccak_lib.keccak_digest(self._state.get(),
+ bfr,
+ c_size_t(self.digest_size))
+ if result:
+ raise ValueError("Error %d while squeezing keccak" % result)
+
+ return get_raw_buffer(bfr)
+
+ def hexdigest(self):
+ """Return the **printable** digest of the message that has been hashed so far.
+
+ :return: The hash digest, computed over the data processed so far.
+ Hexadecimal encoded.
+ :rtype: string
+ """
+
+ return "".join(["%02x" % bord(x) for x in self.digest()])
+
+ def new(self, **kwargs):
+ """Create a fresh Keccak hash object."""
+
+ if "digest_bytes" not in kwargs and "digest_bits" not in kwargs:
+ kwargs["digest_bytes"] = self.digest_size
+
+ return new(**kwargs)
+
+
+def new(**kwargs):
+ """Create a new hash object.
+
+ Args:
+ data (bytes/bytearray/memoryview):
+ The very first chunk of the message to hash.
+ It is equivalent to an early call to :meth:`Keccak_Hash.update`.
+ digest_bytes (integer):
+ The size of the digest, in bytes (28, 32, 48, 64).
+ digest_bits (integer):
+ The size of the digest, in bits (224, 256, 384, 512).
+ update_after_digest (boolean):
+ Whether :meth:`Keccak.digest` can be followed by another
+ :meth:`Keccak.update` (default: ``False``).
+
+ :Return: A :class:`Keccak_Hash` hash object
+ """
+
+ data = kwargs.pop("data", None)
+ update_after_digest = kwargs.pop("update_after_digest", False)
+
+ digest_bytes = kwargs.pop("digest_bytes", None)
+ digest_bits = kwargs.pop("digest_bits", None)
+ if None not in (digest_bytes, digest_bits):
+ raise TypeError("Only one digest parameter must be provided")
+ if (None, None) == (digest_bytes, digest_bits):
+ raise TypeError("Digest size (bits, bytes) not provided")
+ if digest_bytes is not None:
+ if digest_bytes not in (28, 32, 48, 64):
+ raise ValueError("'digest_bytes' must be: 28, 32, 48 or 64")
+ else:
+ if digest_bits not in (224, 256, 384, 512):
+ raise ValueError("'digest_bytes' must be: 224, 256, 384 or 512")
+ digest_bytes = digest_bits // 8
+
+ if kwargs:
+ raise TypeError("Unknown parameters: " + str(kwargs))
+
+ return Keccak_Hash(data, digest_bytes, update_after_digest)
diff --git a/frozen_deps/Cryptodome/Hash/keccak.pyi b/frozen_deps/Cryptodome/Hash/keccak.pyi
new file mode 100644
index 0000000..844d256
--- /dev/null
+++ b/frozen_deps/Cryptodome/Hash/keccak.pyi
@@ -0,0 +1,23 @@
+from typing import Union, Any
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+class Keccak_Hash(object):
+ digest_size: int
+ def __init__(self,
+ data: Buffer,
+ digest_bytes: int,
+ update_after_digest: bool) -> None: ...
+ def update(self, data: Buffer) -> Keccak_Hash: ...
+ def digest(self) -> bytes: ...
+ def hexdigest(self) -> str: ...
+ def new(self,
+ data: Buffer = ...,
+ digest_bytes: int = ...,
+ digest_bits: int = ...,
+ update_after_digest: bool = ...) -> Keccak_Hash: ...
+
+def new(data: Buffer = ...,
+ digest_bytes: int = ...,
+ digest_bits: int = ...,
+ update_after_digest: bool = ...) -> Keccak_Hash: ...
diff --git a/frozen_deps/Cryptodome/IO/PEM.py b/frozen_deps/Cryptodome/IO/PEM.py
new file mode 100644
index 0000000..7655368
--- /dev/null
+++ b/frozen_deps/Cryptodome/IO/PEM.py
@@ -0,0 +1,189 @@
+#
+# Util/PEM.py : Privacy Enhanced Mail utilities
+#
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+__all__ = ['encode', 'decode']
+
+import re
+from binascii import a2b_base64, b2a_base64, hexlify, unhexlify
+
+from Cryptodome.Hash import MD5
+from Cryptodome.Util.Padding import pad, unpad
+from Cryptodome.Cipher import DES, DES3, AES
+from Cryptodome.Protocol.KDF import PBKDF1
+from Cryptodome.Random import get_random_bytes
+from Cryptodome.Util.py3compat import tobytes, tostr
+
+
+def encode(data, marker, passphrase=None, randfunc=None):
+ """Encode a piece of binary data into PEM format.
+
+ Args:
+ data (byte string):
+ The piece of binary data to encode.
+ marker (string):
+ The marker for the PEM block (e.g. "PUBLIC KEY").
+ Note that there is no official master list for all allowed markers.
+ Still, you can refer to the OpenSSL_ source code.
+ passphrase (byte string):
+ If given, the PEM block will be encrypted. The key is derived from
+ the passphrase.
+ randfunc (callable):
+ Random number generation function; it accepts an integer N and returns
+ a byte string of random data, N bytes long. If not given, a new one is
+ instantiated.
+
+ Returns:
+ The PEM block, as a string.
+
+ .. _OpenSSL: https://github.com/openssl/openssl/blob/master/include/openssl/pem.h
+ """
+
+ if randfunc is None:
+ randfunc = get_random_bytes
+
+ out = "-----BEGIN %s-----\n" % marker
+ if passphrase:
+ # We only support 3DES for encryption
+ salt = randfunc(8)
+ key = PBKDF1(passphrase, salt, 16, 1, MD5)
+ key += PBKDF1(key + passphrase, salt, 8, 1, MD5)
+ objenc = DES3.new(key, DES3.MODE_CBC, salt)
+ out += "Proc-Type: 4,ENCRYPTED\nDEK-Info: DES-EDE3-CBC,%s\n\n" %\
+ tostr(hexlify(salt).upper())
+ # Encrypt with PKCS#7 padding
+ data = objenc.encrypt(pad(data, objenc.block_size))
+ elif passphrase is not None:
+ raise ValueError("Empty password")
+
+ # Each BASE64 line can take up to 64 characters (=48 bytes of data)
+ # b2a_base64 adds a new line character!
+ chunks = [tostr(b2a_base64(data[i:i + 48]))
+ for i in range(0, len(data), 48)]
+ out += "".join(chunks)
+ out += "-----END %s-----" % marker
+ return out
+
+
+def _EVP_BytesToKey(data, salt, key_len):
+ d = [ b'' ]
+ m = (key_len + 15 ) // 16
+ for _ in range(m):
+ nd = MD5.new(d[-1] + data + salt).digest()
+ d.append(nd)
+ return b"".join(d)[:key_len]
+
+
+def decode(pem_data, passphrase=None):
+ """Decode a PEM block into binary.
+
+ Args:
+ pem_data (string):
+ The PEM block.
+ passphrase (byte string):
+ If given and the PEM block is encrypted,
+ the key will be derived from the passphrase.
+
+ Returns:
+ A tuple with the binary data, the marker string, and a boolean to
+ indicate if decryption was performed.
+
+ Raises:
+ ValueError: if decoding fails, if the PEM file is encrypted and no passphrase has
+ been provided or if the passphrase is incorrect.
+ """
+
+ # Verify Pre-Encapsulation Boundary
+ r = re.compile(r"\s*-----BEGIN (.*)-----\s+")
+ m = r.match(pem_data)
+ if not m:
+ raise ValueError("Not a valid PEM pre boundary")
+ marker = m.group(1)
+
+ # Verify Post-Encapsulation Boundary
+ r = re.compile(r"-----END (.*)-----\s*$")
+ m = r.search(pem_data)
+ if not m or m.group(1) != marker:
+ raise ValueError("Not a valid PEM post boundary")
+
+ # Removes spaces and slit on lines
+ lines = pem_data.replace(" ", '').split()
+
+ # Decrypts, if necessary
+ if lines[1].startswith('Proc-Type:4,ENCRYPTED'):
+ if not passphrase:
+ raise ValueError("PEM is encrypted, but no passphrase available")
+ DEK = lines[2].split(':')
+ if len(DEK) != 2 or DEK[0] != 'DEK-Info':
+ raise ValueError("PEM encryption format not supported.")
+ algo, salt = DEK[1].split(',')
+ salt = unhexlify(tobytes(salt))
+
+ padding = True
+
+ if algo == "DES-CBC":
+ key = _EVP_BytesToKey(passphrase, salt, 8)
+ objdec = DES.new(key, DES.MODE_CBC, salt)
+ elif algo == "DES-EDE3-CBC":
+ key = _EVP_BytesToKey(passphrase, salt, 24)
+ objdec = DES3.new(key, DES3.MODE_CBC, salt)
+ elif algo == "AES-128-CBC":
+ key = _EVP_BytesToKey(passphrase, salt[:8], 16)
+ objdec = AES.new(key, AES.MODE_CBC, salt)
+ elif algo == "AES-192-CBC":
+ key = _EVP_BytesToKey(passphrase, salt[:8], 24)
+ objdec = AES.new(key, AES.MODE_CBC, salt)
+ elif algo == "AES-256-CBC":
+ key = _EVP_BytesToKey(passphrase, salt[:8], 32)
+ objdec = AES.new(key, AES.MODE_CBC, salt)
+ elif algo.lower() == "id-aes256-gcm":
+ key = _EVP_BytesToKey(passphrase, salt[:8], 32)
+ objdec = AES.new(key, AES.MODE_GCM, nonce=salt)
+ padding = False
+ else:
+ raise ValueError("Unsupport PEM encryption algorithm (%s)." % algo)
+ lines = lines[2:]
+ else:
+ objdec = None
+
+ # Decode body
+ data = a2b_base64(''.join(lines[1:-1]))
+ enc_flag = False
+ if objdec:
+ if padding:
+ data = unpad(objdec.decrypt(data), objdec.block_size)
+ else:
+ # There is no tag, so we don't use decrypt_and_verify
+ data = objdec.decrypt(data)
+ enc_flag = True
+
+ return (data, marker, enc_flag)
diff --git a/frozen_deps/Cryptodome/IO/PEM.pyi b/frozen_deps/Cryptodome/IO/PEM.pyi
new file mode 100644
index 0000000..2e324c4
--- /dev/null
+++ b/frozen_deps/Cryptodome/IO/PEM.pyi
@@ -0,0 +1,10 @@
+from typing import Tuple, Optional, Callable
+
+def encode(data: bytes,
+ marke: str,
+ passphrase: Optional[bytes] = ...,
+ randfunc: Optional[Callable[[int],bytes]] = ...) -> str: ...
+
+
+def decode(pem_data: str,
+ passphrase: Optional[bytes] = ...) -> Tuple[bytes, str, bool]: ...
diff --git a/frozen_deps/Cryptodome/IO/PKCS8.py b/frozen_deps/Cryptodome/IO/PKCS8.py
new file mode 100644
index 0000000..7365476
--- /dev/null
+++ b/frozen_deps/Cryptodome/IO/PKCS8.py
@@ -0,0 +1,231 @@
+#
+# PublicKey/PKCS8.py : PKCS#8 functions
+#
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# 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 *
+
+from Cryptodome.Util.asn1 import (
+ DerNull,
+ DerSequence,
+ DerObjectId,
+ DerOctetString,
+ )
+
+from Cryptodome.IO._PBES import PBES1, PBES2, PbesError
+
+
+__all__ = ['wrap', 'unwrap']
+
+
+def wrap(private_key, key_oid, passphrase=None, protection=None,
+ prot_params=None, key_params=None, randfunc=None):
+ """Wrap a private key into a PKCS#8 blob (clear or encrypted).
+
+ Args:
+
+ private_key (byte string):
+ The private key encoded in binary form. The actual encoding is
+ algorithm specific. In most cases, it is DER.
+
+ key_oid (string):
+ The object identifier (OID) of the private key to wrap.
+ It is a dotted string, like ``1.2.840.113549.1.1.1`` (for RSA keys).
+
+ passphrase (bytes string or string):
+ The secret passphrase from which the wrapping key is derived.
+ Set it only if encryption is required.
+
+ protection (string):
+ The identifier of the algorithm to use for securely wrapping the key.
+ The default value is ``PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC``.
+
+ prot_params (dictionary):
+ Parameters for the protection algorithm.
+
+ +------------------+-----------------------------------------------+
+ | Key | Description |
+ +==================+===============================================+
+ | iteration_count | The KDF algorithm is repeated several times to|
+ | | slow down brute force attacks on passwords |
+ | | (called *N* or CPU/memory cost in scrypt). |
+ | | The default value for PBKDF2 is 1000. |
+ | | The default value for scrypt is 16384. |
+ +------------------+-----------------------------------------------+
+ | salt_size | Salt is used to thwart dictionary and rainbow |
+ | | attacks on passwords. The default value is 8 |
+ | | bytes. |
+ +------------------+-----------------------------------------------+
+ | block_size | *(scrypt only)* Memory-cost (r). The default |
+ | | value is 8. |
+ +------------------+-----------------------------------------------+
+ | parallelization | *(scrypt only)* CPU-cost (p). The default |
+ | | value is 1. |
+ +------------------+-----------------------------------------------+
+
+ key_params (DER object):
+ The algorithm parameters associated to the private key.
+ It is required for algorithms like DSA, but not for others like RSA.
+
+ randfunc (callable):
+ Random number generation function; it should accept a single integer
+ N and return a string of random data, N bytes long.
+ If not specified, a new RNG will be instantiated
+ from :mod:`Cryptodome.Random`.
+
+ Return:
+ The PKCS#8-wrapped private key (possibly encrypted), as a byte string.
+ """
+
+ if key_params is None:
+ key_params = DerNull()
+
+ #
+ # PrivateKeyInfo ::= SEQUENCE {
+ # version Version,
+ # privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
+ # privateKey PrivateKey,
+ # attributes [0] IMPLICIT Attributes OPTIONAL
+ # }
+ #
+ pk_info = DerSequence([
+ 0,
+ DerSequence([
+ DerObjectId(key_oid),
+ key_params
+ ]),
+ DerOctetString(private_key)
+ ])
+ pk_info_der = pk_info.encode()
+
+ if passphrase is None:
+ return pk_info_der
+
+ if not passphrase:
+ raise ValueError("Empty passphrase")
+
+ # Encryption with PBES2
+ passphrase = tobytes(passphrase)
+ if protection is None:
+ protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC'
+ return PBES2.encrypt(pk_info_der, passphrase,
+ protection, prot_params, randfunc)
+
+
+def unwrap(p8_private_key, passphrase=None):
+ """Unwrap a private key from a PKCS#8 blob (clear or encrypted).
+
+ Args:
+ p8_private_key (byte string):
+ The private key wrapped into a PKCS#8 blob, DER encoded.
+ passphrase (byte string or string):
+ The passphrase to use to decrypt the blob (if it is encrypted).
+
+ Return:
+ A tuple containing
+
+ #. the algorithm identifier of the wrapped key (OID, dotted string)
+ #. the private key (byte string, DER encoded)
+ #. the associated parameters (byte string, DER encoded) or ``None``
+
+ Raises:
+ ValueError : if decoding fails
+ """
+
+ if passphrase:
+ passphrase = tobytes(passphrase)
+
+ found = False
+ try:
+ p8_private_key = PBES1.decrypt(p8_private_key, passphrase)
+ found = True
+ except PbesError as e:
+ error_str = "PBES1[%s]" % str(e)
+ except ValueError:
+ error_str = "PBES1[Invalid]"
+
+ if not found:
+ try:
+ p8_private_key = PBES2.decrypt(p8_private_key, passphrase)
+ found = True
+ except PbesError as e:
+ error_str += ",PBES2[%s]" % str(e)
+ except ValueError:
+ error_str += ",PBES2[Invalid]"
+
+ if not found:
+ raise ValueError("Error decoding PKCS#8 (%s)" % error_str)
+
+ pk_info = DerSequence().decode(p8_private_key, nr_elements=(2, 3, 4))
+ if len(pk_info) == 2 and not passphrase:
+ raise ValueError("Not a valid clear PKCS#8 structure "
+ "(maybe it is encrypted?)")
+
+ #
+ # PrivateKeyInfo ::= SEQUENCE {
+ # version Version,
+ # privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
+ # privateKey PrivateKey,
+ # attributes [0] IMPLICIT Attributes OPTIONAL
+ # }
+ # Version ::= INTEGER
+ if pk_info[0] != 0:
+ raise ValueError("Not a valid PrivateKeyInfo SEQUENCE")
+
+ # PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
+ #
+ # EncryptedPrivateKeyInfo ::= SEQUENCE {
+ # encryptionAlgorithm EncryptionAlgorithmIdentifier,
+ # encryptedData EncryptedData
+ # }
+ # EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+
+ # AlgorithmIdentifier ::= SEQUENCE {
+ # algorithm OBJECT IDENTIFIER,
+ # parameters ANY DEFINED BY algorithm OPTIONAL
+ # }
+
+ algo = DerSequence().decode(pk_info[1], nr_elements=(1, 2))
+ algo_oid = DerObjectId().decode(algo[0]).value
+ if len(algo) == 1:
+ algo_params = None
+ else:
+ try:
+ DerNull().decode(algo[1])
+ algo_params = None
+ except:
+ algo_params = algo[1]
+
+ # EncryptedData ::= OCTET STRING
+ private_key = DerOctetString().decode(pk_info[2]).payload
+
+ return (algo_oid, private_key, algo_params)
diff --git a/frozen_deps/Cryptodome/IO/PKCS8.pyi b/frozen_deps/Cryptodome/IO/PKCS8.pyi
new file mode 100644
index 0000000..135b638
--- /dev/null
+++ b/frozen_deps/Cryptodome/IO/PKCS8.pyi
@@ -0,0 +1,14 @@
+from typing import Dict, Tuple, Optional, Union, Callable
+
+from Cryptodome.Util.asn1 import DerObject
+
+def wrap(private_key: bytes,
+ key_oid: str,
+ passphrase: Union[bytes, str] = ...,
+ protection: str = ...,
+ prot_params: Dict = ...,
+ key_params: DerObject = ...,
+ randfunc: Optional[Callable[[int],str]] = ...) -> bytes: ...
+
+
+def unwrap(p8_private_key: bytes, passphrase: Optional[Union[bytes, str]] = ...) -> Tuple[str, bytes, Optional[bytes]]: ...
diff --git a/frozen_deps/Cryptodome/IO/_PBES.py b/frozen_deps/Cryptodome/IO/_PBES.py
new file mode 100644
index 0000000..9ee5385
--- /dev/null
+++ b/frozen_deps/Cryptodome/IO/_PBES.py
@@ -0,0 +1,435 @@
+#
+# PublicKey/_PBES.py : Password-Based Encryption functions
+#
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# 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 import Random
+from Cryptodome.Util.asn1 import (
+ DerSequence, DerOctetString,
+ DerObjectId, DerInteger,
+ )
+
+from Cryptodome.Util.Padding import pad, unpad
+from Cryptodome.Hash import MD5, SHA1, SHA224, SHA256, SHA384, SHA512
+from Cryptodome.Cipher import DES, ARC2, DES3, AES
+from Cryptodome.Protocol.KDF import PBKDF1, PBKDF2, scrypt
+
+_OID_PBE_WITH_MD5_AND_DES_CBC = "1.2.840.113549.1.5.3"
+_OID_PBE_WITH_MD5_AND_RC2_CBC = "1.2.840.113549.1.5.6"
+_OID_PBE_WITH_SHA1_AND_DES_CBC = "1.2.840.113549.1.5.10"
+_OID_PBE_WITH_SHA1_AND_RC2_CBC = "1.2.840.113549.1.5.11"
+
+_OID_PBES2 = "1.2.840.113549.1.5.13"
+
+_OID_PBKDF2 = "1.2.840.113549.1.5.12"
+_OID_SCRYPT = "1.3.6.1.4.1.11591.4.11"
+
+_OID_HMAC_SHA1 = "1.2.840.113549.2.7"
+_OID_HMAC_SHA224 = "1.2.840.113549.2.8"
+_OID_HMAC_SHA256 = "1.2.840.113549.2.9"
+_OID_HMAC_SHA384 = "1.2.840.113549.2.10"
+_OID_HMAC_SHA512 = "1.2.840.113549.2.11"
+
+_OID_DES_EDE3_CBC = "1.2.840.113549.3.7"
+_OID_AES128_CBC = "2.16.840.1.101.3.4.1.2"
+_OID_AES192_CBC = "2.16.840.1.101.3.4.1.22"
+_OID_AES256_CBC = "2.16.840.1.101.3.4.1.42"
+
+
+class PbesError(ValueError):
+ pass
+
+# These are the ASN.1 definitions used by the PBES1/2 logic:
+#
+# EncryptedPrivateKeyInfo ::= SEQUENCE {
+# encryptionAlgorithm EncryptionAlgorithmIdentifier,
+# encryptedData EncryptedData
+# }
+#
+# EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+#
+# EncryptedData ::= OCTET STRING
+#
+# AlgorithmIdentifier ::= SEQUENCE {
+# algorithm OBJECT IDENTIFIER,
+# parameters ANY DEFINED BY algorithm OPTIONAL
+# }
+#
+# PBEParameter ::= SEQUENCE {
+# salt OCTET STRING (SIZE(8)),
+# iterationCount INTEGER
+# }
+#
+# PBES2-params ::= SEQUENCE {
+# keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
+# encryptionScheme AlgorithmIdentifier {{PBES2-Encs}}
+# }
+#
+# PBKDF2-params ::= SEQUENCE {
+# salt CHOICE {
+# specified OCTET STRING,
+# otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}}
+# },
+# iterationCount INTEGER (1..MAX),
+# keyLength INTEGER (1..MAX) OPTIONAL,
+# prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1
+# }
+#
+# scrypt-params ::= SEQUENCE {
+# salt OCTET STRING,
+# costParameter INTEGER (1..MAX),
+# blockSize INTEGER (1..MAX),
+# parallelizationParameter INTEGER (1..MAX),
+# keyLength INTEGER (1..MAX) OPTIONAL
+# }
+
+class PBES1(object):
+ """Deprecated encryption scheme with password-based key derivation
+ (originally defined in PKCS#5 v1.5, but still present in `v2.0`__).
+
+ .. __: http://www.ietf.org/rfc/rfc2898.txt
+ """
+
+ @staticmethod
+ def decrypt(data, passphrase):
+ """Decrypt a piece of data using a passphrase and *PBES1*.
+
+ The algorithm to use is automatically detected.
+
+ :Parameters:
+ data : byte string
+ The piece of data to decrypt.
+ passphrase : byte string
+ The passphrase to use for decrypting the data.
+ :Returns:
+ The decrypted data, as a binary string.
+ """
+
+ enc_private_key_info = DerSequence().decode(data)
+ encrypted_algorithm = DerSequence().decode(enc_private_key_info[0])
+ encrypted_data = DerOctetString().decode(enc_private_key_info[1]).payload
+
+ pbe_oid = DerObjectId().decode(encrypted_algorithm[0]).value
+ cipher_params = {}
+ if pbe_oid == _OID_PBE_WITH_MD5_AND_DES_CBC:
+ # PBE_MD5_DES_CBC
+ hashmod = MD5
+ ciphermod = DES
+ elif pbe_oid == _OID_PBE_WITH_MD5_AND_RC2_CBC:
+ # PBE_MD5_RC2_CBC
+ hashmod = MD5
+ ciphermod = ARC2
+ cipher_params['effective_keylen'] = 64
+ elif pbe_oid == _OID_PBE_WITH_SHA1_AND_DES_CBC:
+ # PBE_SHA1_DES_CBC
+ hashmod = SHA1
+ ciphermod = DES
+ elif pbe_oid == _OID_PBE_WITH_SHA1_AND_RC2_CBC:
+ # PBE_SHA1_RC2_CBC
+ hashmod = SHA1
+ ciphermod = ARC2
+ cipher_params['effective_keylen'] = 64
+ else:
+ raise PbesError("Unknown OID for PBES1")
+
+ pbe_params = DerSequence().decode(encrypted_algorithm[1], nr_elements=2)
+ salt = DerOctetString().decode(pbe_params[0]).payload
+ iterations = pbe_params[1]
+
+ key_iv = PBKDF1(passphrase, salt, 16, iterations, hashmod)
+ key, iv = key_iv[:8], key_iv[8:]
+
+ cipher = ciphermod.new(key, ciphermod.MODE_CBC, iv, **cipher_params)
+ pt = cipher.decrypt(encrypted_data)
+ return unpad(pt, cipher.block_size)
+
+
+class PBES2(object):
+ """Encryption scheme with password-based key derivation
+ (defined in `PKCS#5 v2.0`__).
+
+ .. __: http://www.ietf.org/rfc/rfc2898.txt."""
+
+ @staticmethod
+ def encrypt(data, passphrase, protection, prot_params=None, randfunc=None):
+ """Encrypt a piece of data using a passphrase and *PBES2*.
+
+ :Parameters:
+ data : byte string
+ The piece of data to encrypt.
+ passphrase : byte string
+ The passphrase to use for encrypting the data.
+ protection : string
+ The identifier of the encryption algorithm to use.
+ The default value is '``PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC``'.
+ prot_params : dictionary
+ Parameters of the protection algorithm.
+
+ +------------------+-----------------------------------------------+
+ | Key | Description |
+ +==================+===============================================+
+ | iteration_count | The KDF algorithm is repeated several times to|
+ | | slow down brute force attacks on passwords |
+ | | (called *N* or CPU/memory cost in scrypt). |
+ | | |
+ | | The default value for PBKDF2 is 1 000. |
+ | | The default value for scrypt is 16 384. |
+ +------------------+-----------------------------------------------+
+ | salt_size | Salt is used to thwart dictionary and rainbow |
+ | | attacks on passwords. The default value is 8 |
+ | | bytes. |
+ +------------------+-----------------------------------------------+
+ | block_size | *(scrypt only)* Memory-cost (r). The default |
+ | | value is 8. |
+ +------------------+-----------------------------------------------+
+ | parallelization | *(scrypt only)* CPU-cost (p). The default |
+ | | value is 1. |
+ +------------------+-----------------------------------------------+
+
+
+ randfunc : callable
+ Random number generation function; it should accept
+ a single integer N and return a string of random data,
+ N bytes long. If not specified, a new RNG will be
+ instantiated from ``Cryptodome.Random``.
+
+ :Returns:
+ The encrypted data, as a binary string.
+ """
+
+ if prot_params is None:
+ prot_params = {}
+
+ if randfunc is None:
+ randfunc = Random.new().read
+
+ if protection == 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC':
+ key_size = 24
+ module = DES3
+ cipher_mode = DES3.MODE_CBC
+ enc_oid = _OID_DES_EDE3_CBC
+ elif protection in ('PBKDF2WithHMAC-SHA1AndAES128-CBC',
+ 'scryptAndAES128-CBC'):
+ key_size = 16
+ module = AES
+ cipher_mode = AES.MODE_CBC
+ enc_oid = _OID_AES128_CBC
+ elif protection in ('PBKDF2WithHMAC-SHA1AndAES192-CBC',
+ 'scryptAndAES192-CBC'):
+ key_size = 24
+ module = AES
+ cipher_mode = AES.MODE_CBC
+ enc_oid = _OID_AES192_CBC
+ elif protection in ('PBKDF2WithHMAC-SHA1AndAES256-CBC',
+ 'scryptAndAES256-CBC'):
+ key_size = 32
+ module = AES
+ cipher_mode = AES.MODE_CBC
+ enc_oid = _OID_AES256_CBC
+ else:
+ raise ValueError("Unknown PBES2 mode")
+
+ # Get random data
+ iv = randfunc(module.block_size)
+ salt = randfunc(prot_params.get("salt_size", 8))
+
+ # Derive key from password
+ if protection.startswith('PBKDF2'):
+ count = prot_params.get("iteration_count", 1000)
+ key = PBKDF2(passphrase, salt, key_size, count)
+ kdf_info = DerSequence([
+ DerObjectId(_OID_PBKDF2), # PBKDF2
+ DerSequence([
+ DerOctetString(salt),
+ DerInteger(count)
+ ])
+ ])
+ else:
+ # It must be scrypt
+ count = prot_params.get("iteration_count", 16384)
+ scrypt_r = prot_params.get('block_size', 8)
+ scrypt_p = prot_params.get('parallelization', 1)
+ key = scrypt(passphrase, salt, key_size,
+ count, scrypt_r, scrypt_p)
+ kdf_info = DerSequence([
+ DerObjectId(_OID_SCRYPT), # scrypt
+ DerSequence([
+ DerOctetString(salt),
+ DerInteger(count),
+ DerInteger(scrypt_r),
+ DerInteger(scrypt_p)
+ ])
+ ])
+
+ # Create cipher and use it
+ cipher = module.new(key, cipher_mode, iv)
+ encrypted_data = cipher.encrypt(pad(data, cipher.block_size))
+ enc_info = DerSequence([
+ DerObjectId(enc_oid),
+ DerOctetString(iv)
+ ])
+
+ # Result
+ enc_private_key_info = DerSequence([
+ # encryptionAlgorithm
+ DerSequence([
+ DerObjectId(_OID_PBES2),
+ DerSequence([
+ kdf_info,
+ enc_info
+ ]),
+ ]),
+ DerOctetString(encrypted_data)
+ ])
+ return enc_private_key_info.encode()
+
+ @staticmethod
+ def decrypt(data, passphrase):
+ """Decrypt a piece of data using a passphrase and *PBES2*.
+
+ The algorithm to use is automatically detected.
+
+ :Parameters:
+ data : byte string
+ The piece of data to decrypt.
+ passphrase : byte string
+ The passphrase to use for decrypting the data.
+ :Returns:
+ The decrypted data, as a binary string.
+ """
+
+ enc_private_key_info = DerSequence().decode(data, nr_elements=2)
+ enc_algo = DerSequence().decode(enc_private_key_info[0])
+ encrypted_data = DerOctetString().decode(enc_private_key_info[1]).payload
+
+ pbe_oid = DerObjectId().decode(enc_algo[0]).value
+ if pbe_oid != _OID_PBES2:
+ raise PbesError("Not a PBES2 object")
+
+ pbes2_params = DerSequence().decode(enc_algo[1], nr_elements=2)
+
+ ### Key Derivation Function selection
+ kdf_info = DerSequence().decode(pbes2_params[0], nr_elements=2)
+ kdf_oid = DerObjectId().decode(kdf_info[0]).value
+
+ kdf_key_length = None
+
+ # We only support PBKDF2 or scrypt
+ if kdf_oid == _OID_PBKDF2:
+
+ pbkdf2_params = DerSequence().decode(kdf_info[1], nr_elements=(2, 3, 4))
+ salt = DerOctetString().decode(pbkdf2_params[0]).payload
+ iteration_count = pbkdf2_params[1]
+
+ left = len(pbkdf2_params) - 2
+ idx = 2
+
+ if left > 0:
+ try:
+ kdf_key_length = pbkdf2_params[idx] - 0
+ left -= 1
+ idx += 1
+ except TypeError:
+ pass
+
+ # Default is HMAC-SHA1
+ pbkdf2_prf_oid = "1.2.840.113549.2.7"
+ if left > 0:
+ pbkdf2_prf_algo_id = DerSequence().decode(pbkdf2_params[idx])
+ pbkdf2_prf_oid = DerObjectId().decode(pbkdf2_prf_algo_id[0]).value
+
+ elif kdf_oid == _OID_SCRYPT:
+
+ scrypt_params = DerSequence().decode(kdf_info[1], nr_elements=(4, 5))
+ salt = DerOctetString().decode(scrypt_params[0]).payload
+ iteration_count, scrypt_r, scrypt_p = [scrypt_params[x]
+ for x in (1, 2, 3)]
+ if len(scrypt_params) > 4:
+ kdf_key_length = scrypt_params[4]
+ else:
+ kdf_key_length = None
+ else:
+ raise PbesError("Unsupported PBES2 KDF")
+
+ ### Cipher selection
+ enc_info = DerSequence().decode(pbes2_params[1])
+ enc_oid = DerObjectId().decode(enc_info[0]).value
+
+ if enc_oid == _OID_DES_EDE3_CBC:
+ # DES_EDE3_CBC
+ ciphermod = DES3
+ key_size = 24
+ elif enc_oid == _OID_AES128_CBC:
+ # AES128_CBC
+ ciphermod = AES
+ key_size = 16
+ elif enc_oid == _OID_AES192_CBC:
+ # AES192_CBC
+ ciphermod = AES
+ key_size = 24
+ elif enc_oid == _OID_AES256_CBC:
+ # AES256_CBC
+ ciphermod = AES
+ key_size = 32
+ else:
+ raise PbesError("Unsupported PBES2 cipher")
+
+ if kdf_key_length and kdf_key_length != key_size:
+ raise PbesError("Mismatch between PBES2 KDF parameters"
+ " and selected cipher")
+
+ IV = DerOctetString().decode(enc_info[1]).payload
+
+ # Create cipher
+ if kdf_oid == _OID_PBKDF2:
+ if pbkdf2_prf_oid == _OID_HMAC_SHA1:
+ hmac_hash_module = SHA1
+ elif pbkdf2_prf_oid == _OID_HMAC_SHA224:
+ hmac_hash_module = SHA224
+ elif pbkdf2_prf_oid == _OID_HMAC_SHA256:
+ hmac_hash_module = SHA256
+ elif pbkdf2_prf_oid == _OID_HMAC_SHA384:
+ hmac_hash_module = SHA384
+ elif pbkdf2_prf_oid == _OID_HMAC_SHA512:
+ hmac_hash_module = SHA512
+ else:
+ raise PbesError("Unsupported HMAC %s" % pbkdf2_prf_oid)
+
+ key = PBKDF2(passphrase, salt, key_size, iteration_count,
+ hmac_hash_module=hmac_hash_module)
+ else:
+ key = scrypt(passphrase, salt, key_size, iteration_count,
+ scrypt_r, scrypt_p)
+ cipher = ciphermod.new(key, ciphermod.MODE_CBC, IV)
+
+ # Decrypt data
+ pt = cipher.decrypt(encrypted_data)
+ return unpad(pt, cipher.block_size)
diff --git a/frozen_deps/Cryptodome/IO/_PBES.pyi b/frozen_deps/Cryptodome/IO/_PBES.pyi
new file mode 100644
index 0000000..a8a34ce
--- /dev/null
+++ b/frozen_deps/Cryptodome/IO/_PBES.pyi
@@ -0,0 +1,19 @@
+from typing import Dict, Optional, Callable
+
+class PbesError(ValueError):
+ ...
+
+class PBES1(object):
+ @staticmethod
+ def decrypt(data: bytes, passphrase: bytes) -> bytes: ...
+
+class PBES2(object):
+ @staticmethod
+ def encrypt(data: bytes,
+ passphrase: bytes,
+ protection: str,
+ prot_params: Optional[Dict] = ...,
+ randfunc: Optional[Callable[[int],bytes]] = ...) -> bytes: ...
+
+ @staticmethod
+ def decrypt(data:bytes, passphrase: bytes) -> bytes: ...
diff --git a/frozen_deps/Cryptodome/IO/__init__.py b/frozen_deps/Cryptodome/IO/__init__.py
new file mode 100644
index 0000000..85a0d0b
--- /dev/null
+++ b/frozen_deps/Cryptodome/IO/__init__.py
@@ -0,0 +1,31 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+__all__ = ['PEM', 'PKCS8']
diff --git a/frozen_deps/Cryptodome/Math/Numbers.py b/frozen_deps/Cryptodome/Math/Numbers.py
new file mode 100644
index 0000000..c9ff848
--- /dev/null
+++ b/frozen_deps/Cryptodome/Math/Numbers.py
@@ -0,0 +1,42 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+__all__ = ["Integer"]
+
+try:
+ from Cryptodome.Math._IntegerGMP import IntegerGMP as Integer
+ from Cryptodome.Math._IntegerGMP import implementation as _implementation
+except (ImportError, OSError, AttributeError):
+ try:
+ from Cryptodome.Math._IntegerCustom import IntegerCustom as Integer
+ from Cryptodome.Math._IntegerCustom import implementation as _implementation
+ except (ImportError, OSError):
+ from Cryptodome.Math._IntegerNative import IntegerNative as Integer
+ _implementation = {}
diff --git a/frozen_deps/Cryptodome/Math/Numbers.pyi b/frozen_deps/Cryptodome/Math/Numbers.pyi
new file mode 100644
index 0000000..2285a3b
--- /dev/null
+++ b/frozen_deps/Cryptodome/Math/Numbers.pyi
@@ -0,0 +1,4 @@
+from Cryptodome.Math._IntegerBase import IntegerBase
+
+class Integer(IntegerBase):
+ pass
diff --git a/frozen_deps/Cryptodome/Math/Primality.py b/frozen_deps/Cryptodome/Math/Primality.py
new file mode 100644
index 0000000..08ea3ff
--- /dev/null
+++ b/frozen_deps/Cryptodome/Math/Primality.py
@@ -0,0 +1,368 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+"""Functions to create and test prime numbers.
+
+:undocumented: __package__
+"""
+
+from Cryptodome import Random
+from Cryptodome.Math.Numbers import Integer
+
+from Cryptodome.Util.py3compat import iter_range
+
+COMPOSITE = 0
+PROBABLY_PRIME = 1
+
+
+def miller_rabin_test(candidate, iterations, randfunc=None):
+ """Perform a Miller-Rabin primality test on an integer.
+
+ The test is specified in Section C.3.1 of `FIPS PUB 186-4`__.
+
+ :Parameters:
+ candidate : integer
+ The number to test for primality.
+ iterations : integer
+ The maximum number of iterations to perform before
+ declaring a candidate a probable prime.
+ randfunc : callable
+ An RNG function where bases are taken from.
+
+ :Returns:
+ ``Primality.COMPOSITE`` or ``Primality.PROBABLY_PRIME``.
+
+ .. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
+ """
+
+ if not isinstance(candidate, Integer):
+ candidate = Integer(candidate)
+
+ if candidate in (1, 2, 3, 5):
+ return PROBABLY_PRIME
+
+ if candidate.is_even():
+ return COMPOSITE
+
+ one = Integer(1)
+ minus_one = Integer(candidate - 1)
+
+ if randfunc is None:
+ randfunc = Random.new().read
+
+ # Step 1 and 2
+ m = Integer(minus_one)
+ a = 0
+ while m.is_even():
+ m >>= 1
+ a += 1
+
+ # Skip step 3
+
+ # Step 4
+ for i in iter_range(iterations):
+
+ # Step 4.1-2
+ base = 1
+ while base in (one, minus_one):
+ base = Integer.random_range(min_inclusive=2,
+ max_inclusive=candidate - 2)
+ assert(2 <= base <= candidate - 2)
+
+ # Step 4.3-4.4
+ z = pow(base, m, candidate)
+ if z in (one, minus_one):
+ continue
+
+ # Step 4.5
+ for j in iter_range(1, a):
+ z = pow(z, 2, candidate)
+ if z == minus_one:
+ break
+ if z == one:
+ return COMPOSITE
+ else:
+ return COMPOSITE
+
+ # Step 5
+ return PROBABLY_PRIME
+
+
+def lucas_test(candidate):
+ """Perform a Lucas primality test on an integer.
+
+ The test is specified in Section C.3.3 of `FIPS PUB 186-4`__.
+
+ :Parameters:
+ candidate : integer
+ The number to test for primality.
+
+ :Returns:
+ ``Primality.COMPOSITE`` or ``Primality.PROBABLY_PRIME``.
+
+ .. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
+ """
+
+ if not isinstance(candidate, Integer):
+ candidate = Integer(candidate)
+
+ # Step 1
+ if candidate in (1, 2, 3, 5):
+ return PROBABLY_PRIME
+ if candidate.is_even() or candidate.is_perfect_square():
+ return COMPOSITE
+
+ # Step 2
+ def alternate():
+ value = 5
+ while True:
+ yield value
+ if value > 0:
+ value += 2
+ else:
+ value -= 2
+ value = -value
+
+ for D in alternate():
+ if candidate in (D, -D):
+ continue
+ js = Integer.jacobi_symbol(D, candidate)
+ if js == 0:
+ return COMPOSITE
+ if js == -1:
+ break
+ # Found D. P=1 and Q=(1-D)/4 (note that Q is guaranteed to be an integer)
+
+ # Step 3
+ # This is \delta(n) = n - jacobi(D/n)
+ K = candidate + 1
+ # Step 4
+ r = K.size_in_bits() - 1
+ # Step 5
+ # U_1=1 and V_1=P
+ U_i = Integer(1)
+ V_i = Integer(1)
+ U_temp = Integer(0)
+ V_temp = Integer(0)
+ # Step 6
+ for i in iter_range(r - 1, -1, -1):
+ # Square
+ # U_temp = U_i * V_i % candidate
+ U_temp.set(U_i)
+ U_temp *= V_i
+ U_temp %= candidate
+ # V_temp = (((V_i ** 2 + (U_i ** 2 * D)) * K) >> 1) % candidate
+ V_temp.set(U_i)
+ V_temp *= U_i
+ V_temp *= D
+ V_temp.multiply_accumulate(V_i, V_i)
+ if V_temp.is_odd():
+ V_temp += candidate
+ V_temp >>= 1
+ V_temp %= candidate
+ # Multiply
+ if K.get_bit(i):
+ # U_i = (((U_temp + V_temp) * K) >> 1) % candidate
+ U_i.set(U_temp)
+ U_i += V_temp
+ if U_i.is_odd():
+ U_i += candidate
+ U_i >>= 1
+ U_i %= candidate
+ # V_i = (((V_temp + U_temp * D) * K) >> 1) % candidate
+ V_i.set(V_temp)
+ V_i.multiply_accumulate(U_temp, D)
+ if V_i.is_odd():
+ V_i += candidate
+ V_i >>= 1
+ V_i %= candidate
+ else:
+ U_i.set(U_temp)
+ V_i.set(V_temp)
+ # Step 7
+ if U_i == 0:
+ return PROBABLY_PRIME
+ return COMPOSITE
+
+
+from Cryptodome.Util.number import sieve_base as _sieve_base_large
+## The optimal number of small primes to use for the sieve
+## is probably dependent on the platform and the candidate size
+_sieve_base = set(_sieve_base_large[:100])
+
+
+def test_probable_prime(candidate, randfunc=None):
+ """Test if a number is prime.
+
+ A number is qualified as prime if it passes a certain
+ number of Miller-Rabin tests (dependent on the size
+ of the number, but such that probability of a false
+ positive is less than 10^-30) and a single Lucas test.
+
+ For instance, a 1024-bit candidate will need to pass
+ 4 Miller-Rabin tests.
+
+ :Parameters:
+ candidate : integer
+ The number to test for primality.
+ randfunc : callable
+ The routine to draw random bytes from to select Miller-Rabin bases.
+ :Returns:
+ ``PROBABLE_PRIME`` if the number if prime with very high probability.
+ ``COMPOSITE`` if the number is a composite.
+ For efficiency reasons, ``COMPOSITE`` is also returned for small primes.
+ """
+
+ if randfunc is None:
+ randfunc = Random.new().read
+
+ if not isinstance(candidate, Integer):
+ candidate = Integer(candidate)
+
+ # First, check trial division by the smallest primes
+ if int(candidate) in _sieve_base:
+ return PROBABLY_PRIME
+ try:
+ map(candidate.fail_if_divisible_by, _sieve_base)
+ except ValueError:
+ return COMPOSITE
+
+ # These are the number of Miller-Rabin iterations s.t. p(k, t) < 1E-30,
+ # with p(k, t) being the probability that a randomly chosen k-bit number
+ # is composite but still survives t MR iterations.
+ mr_ranges = ((220, 30), (280, 20), (390, 15), (512, 10),
+ (620, 7), (740, 6), (890, 5), (1200, 4),
+ (1700, 3), (3700, 2))
+
+ bit_size = candidate.size_in_bits()
+ try:
+ mr_iterations = list(filter(lambda x: bit_size < x[0],
+ mr_ranges))[0][1]
+ except IndexError:
+ mr_iterations = 1
+
+ if miller_rabin_test(candidate, mr_iterations,
+ randfunc=randfunc) == COMPOSITE:
+ return COMPOSITE
+ if lucas_test(candidate) == COMPOSITE:
+ return COMPOSITE
+ return PROBABLY_PRIME
+
+
+def generate_probable_prime(**kwargs):
+ """Generate a random probable prime.
+
+ The prime will not have any specific properties
+ (e.g. it will not be a *strong* prime).
+
+ Random numbers are evaluated for primality until one
+ passes all tests, consisting of a certain number of
+ Miller-Rabin tests with random bases followed by
+ a single Lucas test.
+
+ The number of Miller-Rabin iterations is chosen such that
+ the probability that the output number is a non-prime is
+ less than 1E-30 (roughly 2^{-100}).
+
+ This approach is compliant to `FIPS PUB 186-4`__.
+
+ :Keywords:
+ exact_bits : integer
+ The desired size in bits of the probable prime.
+ It must be at least 160.
+ randfunc : callable
+ An RNG function where candidate primes are taken from.
+ prime_filter : callable
+ A function that takes an Integer as parameter and returns
+ True if the number can be passed to further primality tests,
+ False if it should be immediately discarded.
+
+ :Return:
+ A probable prime in the range 2^exact_bits > p > 2^(exact_bits-1).
+
+ .. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
+ """
+
+ exact_bits = kwargs.pop("exact_bits", None)
+ randfunc = kwargs.pop("randfunc", None)
+ prime_filter = kwargs.pop("prime_filter", lambda x: True)
+ if kwargs:
+ raise ValueError("Unknown parameters: " + kwargs.keys())
+
+ if exact_bits is None:
+ raise ValueError("Missing exact_bits parameter")
+ if exact_bits < 160:
+ raise ValueError("Prime number is not big enough.")
+
+ if randfunc is None:
+ randfunc = Random.new().read
+
+ result = COMPOSITE
+ while result == COMPOSITE:
+ candidate = Integer.random(exact_bits=exact_bits,
+ randfunc=randfunc) | 1
+ if not prime_filter(candidate):
+ continue
+ result = test_probable_prime(candidate, randfunc)
+ return candidate
+
+
+def generate_probable_safe_prime(**kwargs):
+ """Generate a random, probable safe prime.
+
+ Note this operation is much slower than generating a simple prime.
+
+ :Keywords:
+ exact_bits : integer
+ The desired size in bits of the probable safe prime.
+ randfunc : callable
+ An RNG function where candidate primes are taken from.
+
+ :Return:
+ A probable safe prime in the range
+ 2^exact_bits > p > 2^(exact_bits-1).
+ """
+
+ exact_bits = kwargs.pop("exact_bits", None)
+ randfunc = kwargs.pop("randfunc", None)
+ if kwargs:
+ raise ValueError("Unknown parameters: " + kwargs.keys())
+
+ if randfunc is None:
+ randfunc = Random.new().read
+
+ result = COMPOSITE
+ while result == COMPOSITE:
+ q = generate_probable_prime(exact_bits=exact_bits - 1, randfunc=randfunc)
+ candidate = q * 2 + 1
+ if candidate.size_in_bits() != exact_bits:
+ continue
+ result = test_probable_prime(candidate, randfunc=randfunc)
+ return candidate
diff --git a/frozen_deps/Cryptodome/Math/Primality.pyi b/frozen_deps/Cryptodome/Math/Primality.pyi
new file mode 100644
index 0000000..7813483
--- /dev/null
+++ b/frozen_deps/Cryptodome/Math/Primality.pyi
@@ -0,0 +1,18 @@
+from typing import Callable, Optional, Union, Set
+
+PrimeResult = int
+
+COMPOSITE: PrimeResult
+PROBABLY_PRIME: PrimeResult
+
+def miller_rabin_test(candidate: int, iterations: int, randfunc: Optional[Callable[[int],bytes]]=None) -> PrimeResult: ...
+def lucas_test(candidate: int) -> PrimeResult: ...
+_sieve_base: Set[int]
+def test_probable_prime(candidate: int, randfunc: Optional[Callable[[int],bytes]]=None) -> PrimeResult: ...
+def generate_probable_prime(*,
+ exact_bits: int = ...,
+ randfunc: Callable[[int],bytes] = ...,
+ prime_filter: Callable[[int],bool] = ...) -> int: ...
+def generate_probable_safe_prime(*,
+ exact_bits: int = ...,
+ randfunc: Callable[[int],bytes] = ...) -> int: ...
diff --git a/frozen_deps/Cryptodome/Math/_IntegerBase.py b/frozen_deps/Cryptodome/Math/_IntegerBase.py
new file mode 100644
index 0000000..f8cf333
--- /dev/null
+++ b/frozen_deps/Cryptodome/Math/_IntegerBase.py
@@ -0,0 +1,392 @@
+# ===================================================================
+#
+# Copyright (c) 2018, Helder Eijs <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+import abc
+
+from Cryptodome.Util.py3compat import iter_range, bord, bchr, ABC
+
+from Cryptodome import Random
+
+
+class IntegerBase(ABC):
+
+ # Conversions
+ @abc.abstractmethod
+ def __int__(self):
+ pass
+
+ @abc.abstractmethod
+ def __str__(self):
+ pass
+
+ @abc.abstractmethod
+ def __repr__(self):
+ pass
+
+ @abc.abstractmethod
+ def to_bytes(self, block_size=0):
+ pass
+
+ @staticmethod
+ @abc.abstractmethod
+ def from_bytes(byte_string):
+ pass
+
+ # Relations
+ @abc.abstractmethod
+ def __eq__(self, term):
+ pass
+
+ @abc.abstractmethod
+ def __ne__(self, term):
+ pass
+
+ @abc.abstractmethod
+ def __lt__(self, term):
+ pass
+
+ @abc.abstractmethod
+ def __le__(self, term):
+ pass
+
+ @abc.abstractmethod
+ def __gt__(self, term):
+ pass
+
+ @abc.abstractmethod
+ def __ge__(self, term):
+ pass
+
+ @abc.abstractmethod
+ def __nonzero__(self):
+ pass
+ __bool__ = __nonzero__
+
+ @abc.abstractmethod
+ def is_negative(self):
+ pass
+
+ # Arithmetic operations
+ @abc.abstractmethod
+ def __add__(self, term):
+ pass
+
+ @abc.abstractmethod
+ def __sub__(self, term):
+ pass
+
+ @abc.abstractmethod
+ def __mul__(self, factor):
+ pass
+
+ @abc.abstractmethod
+ def __floordiv__(self, divisor):
+ pass
+
+ @abc.abstractmethod
+ def __mod__(self, divisor):
+ pass
+
+ @abc.abstractmethod
+ def inplace_pow(self, exponent, modulus=None):
+ pass
+
+ @abc.abstractmethod
+ def __pow__(self, exponent, modulus=None):
+ pass
+
+ @abc.abstractmethod
+ def __abs__(self):
+ pass
+
+ @abc.abstractmethod
+ def sqrt(self, modulus=None):
+ pass
+
+ @abc.abstractmethod
+ def __iadd__(self, term):
+ pass
+
+ @abc.abstractmethod
+ def __isub__(self, term):
+ pass
+
+ @abc.abstractmethod
+ def __imul__(self, term):
+ pass
+
+ @abc.abstractmethod
+ def __imod__(self, term):
+ pass
+
+ # Boolean/bit operations
+ @abc.abstractmethod
+ def __and__(self, term):
+ pass
+
+ @abc.abstractmethod
+ def __or__(self, term):
+ pass
+
+ @abc.abstractmethod
+ def __rshift__(self, pos):
+ pass
+
+ @abc.abstractmethod
+ def __irshift__(self, pos):
+ pass
+
+ @abc.abstractmethod
+ def __lshift__(self, pos):
+ pass
+
+ @abc.abstractmethod
+ def __ilshift__(self, pos):
+ pass
+
+ @abc.abstractmethod
+ def get_bit(self, n):
+ pass
+
+ # Extra
+ @abc.abstractmethod
+ def is_odd(self):
+ pass
+
+ @abc.abstractmethod
+ def is_even(self):
+ pass
+
+ @abc.abstractmethod
+ def size_in_bits(self):
+ pass
+
+ @abc.abstractmethod
+ def size_in_bytes(self):
+ pass
+
+ @abc.abstractmethod
+ def is_perfect_square(self):
+ pass
+
+ @abc.abstractmethod
+ def fail_if_divisible_by(self, small_prime):
+ pass
+
+ @abc.abstractmethod
+ def multiply_accumulate(self, a, b):
+ pass
+
+ @abc.abstractmethod
+ def set(self, source):
+ pass
+
+ @abc.abstractmethod
+ def inplace_inverse(self, modulus):
+ pass
+
+ @abc.abstractmethod
+ def inverse(self, modulus):
+ pass
+
+ @abc.abstractmethod
+ def gcd(self, term):
+ pass
+
+ @abc.abstractmethod
+ def lcm(self, term):
+ pass
+
+ @staticmethod
+ @abc.abstractmethod
+ def jacobi_symbol(a, n):
+ pass
+
+ @staticmethod
+ def _tonelli_shanks(n, p):
+ """Tonelli-shanks algorithm for computing the square root
+ of n modulo a prime p.
+
+ n must be in the range [0..p-1].
+ p must be at least even.
+
+ The return value r is the square root of modulo p. If non-zero,
+ another solution will also exist (p-r).
+
+ Note we cannot assume that p is really a prime: if it's not,
+ we can either raise an exception or return the correct value.
+ """
+
+ # See https://rosettacode.org/wiki/Tonelli-Shanks_algorithm
+
+ if n in (0, 1):
+ return n
+
+ if p % 4 == 3:
+ root = pow(n, (p + 1) // 4, p)
+ if pow(root, 2, p) != n:
+ raise ValueError("Cannot compute square root")
+ return root
+
+ s = 1
+ q = (p - 1) // 2
+ while not (q & 1):
+ s += 1
+ q >>= 1
+
+ z = n.__class__(2)
+ while True:
+ euler = pow(z, (p - 1) // 2, p)
+ if euler == 1:
+ z += 1
+ continue
+ if euler == p - 1:
+ break
+ # Most probably p is not a prime
+ raise ValueError("Cannot compute square root")
+
+ m = s
+ c = pow(z, q, p)
+ t = pow(n, q, p)
+ r = pow(n, (q + 1) // 2, p)
+
+ while t != 1:
+ for i in iter_range(0, m):
+ if pow(t, 2**i, p) == 1:
+ break
+ if i == m:
+ raise ValueError("Cannot compute square root of %d mod %d" % (n, p))
+ b = pow(c, 2**(m - i - 1), p)
+ m = i
+ c = b**2 % p
+ t = (t * b**2) % p
+ r = (r * b) % p
+
+ if pow(r, 2, p) != n:
+ raise ValueError("Cannot compute square root")
+
+ return r
+
+ @classmethod
+ def random(cls, **kwargs):
+ """Generate a random natural integer of a certain size.
+
+ :Keywords:
+ exact_bits : positive integer
+ The length in bits of the resulting random Integer number.
+ The number is guaranteed to fulfil the relation:
+
+ 2^bits > result >= 2^(bits - 1)
+
+ max_bits : positive integer
+ The maximum length in bits of the resulting random Integer number.
+ The number is guaranteed to fulfil the relation:
+
+ 2^bits > result >=0
+
+ randfunc : callable
+ A function that returns a random byte string. The length of the
+ byte string is passed as parameter. Optional.
+ If not provided (or ``None``), randomness is read from the system RNG.
+
+ :Return: a Integer object
+ """
+
+ exact_bits = kwargs.pop("exact_bits", None)
+ max_bits = kwargs.pop("max_bits", None)
+ randfunc = kwargs.pop("randfunc", None)
+
+ if randfunc is None:
+ randfunc = Random.new().read
+
+ if exact_bits is None and max_bits is None:
+ raise ValueError("Either 'exact_bits' or 'max_bits' must be specified")
+
+ if exact_bits is not None and max_bits is not None:
+ raise ValueError("'exact_bits' and 'max_bits' are mutually exclusive")
+
+ bits = exact_bits or max_bits
+ bytes_needed = ((bits - 1) // 8) + 1
+ significant_bits_msb = 8 - (bytes_needed * 8 - bits)
+ msb = bord(randfunc(1)[0])
+ if exact_bits is not None:
+ msb |= 1 << (significant_bits_msb - 1)
+ msb &= (1 << significant_bits_msb) - 1
+
+ return cls.from_bytes(bchr(msb) + randfunc(bytes_needed - 1))
+
+ @classmethod
+ def random_range(cls, **kwargs):
+ """Generate a random integer within a given internal.
+
+ :Keywords:
+ min_inclusive : integer
+ The lower end of the interval (inclusive).
+ max_inclusive : integer
+ The higher end of the interval (inclusive).
+ max_exclusive : integer
+ The higher end of the interval (exclusive).
+ randfunc : callable
+ A function that returns a random byte string. The length of the
+ byte string is passed as parameter. Optional.
+ If not provided (or ``None``), randomness is read from the system RNG.
+ :Returns:
+ An Integer randomly taken in the given interval.
+ """
+
+ min_inclusive = kwargs.pop("min_inclusive", None)
+ max_inclusive = kwargs.pop("max_inclusive", None)
+ max_exclusive = kwargs.pop("max_exclusive", None)
+ randfunc = kwargs.pop("randfunc", None)
+
+ if kwargs:
+ raise ValueError("Unknown keywords: " + str(kwargs.keys))
+ if None not in (max_inclusive, max_exclusive):
+ raise ValueError("max_inclusive and max_exclusive cannot be both"
+ " specified")
+ if max_exclusive is not None:
+ max_inclusive = max_exclusive - 1
+ if None in (min_inclusive, max_inclusive):
+ raise ValueError("Missing keyword to identify the interval")
+
+ if randfunc is None:
+ randfunc = Random.new().read
+
+ norm_maximum = max_inclusive - min_inclusive
+ bits_needed = cls(norm_maximum).size_in_bits()
+
+ norm_candidate = -1
+ while not 0 <= norm_candidate <= norm_maximum:
+ norm_candidate = cls.random(
+ max_bits=bits_needed,
+ randfunc=randfunc
+ )
+ return norm_candidate + min_inclusive
+
diff --git a/frozen_deps/Cryptodome/Math/_IntegerBase.pyi b/frozen_deps/Cryptodome/Math/_IntegerBase.pyi
new file mode 100644
index 0000000..3f534db
--- /dev/null
+++ b/frozen_deps/Cryptodome/Math/_IntegerBase.pyi
@@ -0,0 +1,61 @@
+from typing import Optional, Union, Callable
+
+RandFunc = Callable[[int],int]
+
+class IntegerBase:
+
+ def __int__(self) -> int: ...
+ def __str__(self) -> str: ...
+ def __repr__(self) -> str: ...
+ def to_bytes(self, block_size: Optional[int]=0) -> bytes: ...
+ @staticmethod
+ def from_bytes(byte_string: bytes) -> IntegerBase: ...
+ def __eq__(self, term: object) -> bool: ...
+ def __ne__(self, term: object) -> bool: ...
+ def __lt__(self, term: Union[IntegerBase, int]) -> bool: ...
+ def __le__(self, term: Union[IntegerBase, int]) -> bool: ...
+ def __gt__(self, term: Union[IntegerBase, int]) -> bool: ...
+ def __ge__(self, term: Union[IntegerBase, int]) -> bool: ...
+ def __nonzero__(self) -> bool: ...
+ def is_negative(self) -> bool: ...
+ def __add__(self, term: Union[IntegerBase, int]) -> IntegerBase: ...
+ def __sub__(self, term: Union[IntegerBase, int]) -> IntegerBase: ...
+ def __mul__(self, term: Union[IntegerBase, int]) -> IntegerBase: ...
+ def __floordiv__(self, divisor: Union[IntegerBase, int]) -> IntegerBase: ...
+ def __mod__(self, divisor: Union[IntegerBase, int]) -> IntegerBase: ...
+ def inplace_pow(self, exponent: int, modulus: Optional[Union[IntegerBase, int]]=None) -> IntegerBase: ...
+ def __pow__(self, exponent: int, modulus: Optional[int]) -> IntegerBase: ...
+ def __abs__(self) -> IntegerBase: ...
+ def sqrt(self, modulus: Optional[int]) -> IntegerBase: ...
+ def __iadd__(self, term: Union[IntegerBase, int]) -> IntegerBase: ...
+ def __isub__(self, term: Union[IntegerBase, int]) -> IntegerBase: ...
+ def __imul__(self, term: Union[IntegerBase, int]) -> IntegerBase: ...
+ def __imod__(self, divisor: Union[IntegerBase, int]) -> IntegerBase: ...
+ def __and__(self, term: Union[IntegerBase, int]) -> IntegerBase: ...
+ def __or__(self, term: Union[IntegerBase, int]) -> IntegerBase: ...
+ def __rshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ...
+ def __irshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ...
+ def __lshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ...
+ def __ilshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ...
+ def get_bit(self, n: int) -> bool: ...
+ def is_odd(self) -> bool: ...
+ def is_even(self) -> bool: ...
+ def size_in_bits(self) -> int: ...
+ def size_in_bytes(self) -> int: ...
+ def is_perfect_square(self) -> bool: ...
+ def fail_if_divisible_by(self, small_prime: Union[IntegerBase, int]) -> None: ...
+ def multiply_accumulate(self, a: Union[IntegerBase, int], b: Union[IntegerBase, int]) -> IntegerBase: ...
+ def set(self, source: Union[IntegerBase, int]) -> IntegerBase: ...
+ def inplace_inverse(self, modulus: Union[IntegerBase, int]) -> IntegerBase: ...
+ def inverse(self, modulus: Union[IntegerBase, int]) -> IntegerBase: ...
+ def gcd(self, term: Union[IntegerBase, int]) -> IntegerBase: ...
+ def lcm(self, term: Union[IntegerBase, int]) -> IntegerBase: ...
+ @staticmethod
+ def jacobi_symbol(a: Union[IntegerBase, int], n: Union[IntegerBase, int]) -> IntegerBase: ...
+ @staticmethod
+ def _tonelli_shanks(n: Union[IntegerBase, int], p: Union[IntegerBase, int]) -> IntegerBase : ...
+ @classmethod
+ def random(cls, **kwargs: Union[int,RandFunc]) -> IntegerBase : ...
+ @classmethod
+ def random_range(cls, **kwargs: Union[int,RandFunc]) -> IntegerBase : ...
+
diff --git a/frozen_deps/Cryptodome/Math/_IntegerCustom.py b/frozen_deps/Cryptodome/Math/_IntegerCustom.py
new file mode 100644
index 0000000..b626014
--- /dev/null
+++ b/frozen_deps/Cryptodome/Math/_IntegerCustom.py
@@ -0,0 +1,111 @@
+# ===================================================================
+#
+# Copyright (c) 2018, Helder Eijs <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+from ._IntegerNative import IntegerNative
+
+from Cryptodome.Util.number import long_to_bytes, bytes_to_long
+
+from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib,
+ create_string_buffer,
+ get_raw_buffer, backend,
+ c_size_t, c_ulonglong)
+
+
+from Cryptodome.Random.random import getrandbits
+
+c_defs = """
+int monty_pow(const uint8_t *base,
+ const uint8_t *exp,
+ const uint8_t *modulus,
+ uint8_t *out,
+ size_t len,
+ uint64_t seed);
+"""
+
+
+_raw_montgomery = load_pycryptodome_raw_lib("Cryptodome.Math._modexp", c_defs)
+implementation = {"library": "custom", "api": backend}
+
+
+class IntegerCustom(IntegerNative):
+
+ @staticmethod
+ def from_bytes(byte_string):
+ return IntegerCustom(bytes_to_long(byte_string))
+
+ def inplace_pow(self, exponent, modulus=None):
+ exp_value = int(exponent)
+ if exp_value < 0:
+ raise ValueError("Exponent must not be negative")
+
+ # No modular reduction
+ if modulus is None:
+ self._value = pow(self._value, exp_value)
+ return self
+
+ # With modular reduction
+ mod_value = int(modulus)
+ if mod_value < 0:
+ raise ValueError("Modulus must be positive")
+ if mod_value == 0:
+ raise ZeroDivisionError("Modulus cannot be zero")
+
+ # C extension only works with odd moduli
+ if (mod_value & 1) == 0:
+ self._value = pow(self._value, exp_value, mod_value)
+ return self
+
+ # C extension only works with bases smaller than modulus
+ if self._value >= mod_value:
+ self._value %= mod_value
+
+ max_len = len(long_to_bytes(max(self._value, exp_value, mod_value)))
+
+ base_b = long_to_bytes(self._value, max_len)
+ exp_b = long_to_bytes(exp_value, max_len)
+ modulus_b = long_to_bytes(mod_value, max_len)
+
+ out = create_string_buffer(max_len)
+
+ error = _raw_montgomery.monty_pow(
+ out,
+ base_b,
+ exp_b,
+ modulus_b,
+ c_size_t(max_len),
+ c_ulonglong(getrandbits(64))
+ )
+
+ if error:
+ raise ValueError("monty_pow failed with error: %d" % error)
+
+ result = bytes_to_long(get_raw_buffer(out))
+ self._value = result
+ return self
diff --git a/frozen_deps/Cryptodome/Math/_IntegerCustom.pyi b/frozen_deps/Cryptodome/Math/_IntegerCustom.pyi
new file mode 100644
index 0000000..2dd75c7
--- /dev/null
+++ b/frozen_deps/Cryptodome/Math/_IntegerCustom.pyi
@@ -0,0 +1,8 @@
+from typing import Any
+
+from ._IntegerNative import IntegerNative
+
+_raw_montgomery = Any
+
+class IntegerCustom(IntegerNative):
+ pass
diff --git a/frozen_deps/Cryptodome/Math/_IntegerGMP.py b/frozen_deps/Cryptodome/Math/_IntegerGMP.py
new file mode 100644
index 0000000..c860020
--- /dev/null
+++ b/frozen_deps/Cryptodome/Math/_IntegerGMP.py
@@ -0,0 +1,708 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# 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.Util.py3compat import tobytes, is_native_int
+
+from Cryptodome.Util._raw_api import (backend, load_lib,
+ get_raw_buffer, get_c_string,
+ null_pointer, create_string_buffer,
+ c_ulong, c_size_t)
+
+from ._IntegerBase import IntegerBase
+
+gmp_defs = """typedef unsigned long UNIX_ULONG;
+ typedef struct { int a; int b; void *c; } MPZ;
+ typedef MPZ mpz_t[1];
+ typedef UNIX_ULONG mp_bitcnt_t;
+ void __gmpz_init (mpz_t x);
+ void __gmpz_init_set (mpz_t rop, const mpz_t op);
+ void __gmpz_init_set_ui (mpz_t rop, UNIX_ULONG op);
+ int __gmp_sscanf (const char *s, const char *fmt, ...);
+ void __gmpz_set (mpz_t rop, const mpz_t op);
+ int __gmp_snprintf (uint8_t *buf, size_t size, const char *fmt, ...);
+ void __gmpz_add (mpz_t rop, const mpz_t op1, const mpz_t op2);
+ void __gmpz_add_ui (mpz_t rop, const mpz_t op1, UNIX_ULONG op2);
+ void __gmpz_sub_ui (mpz_t rop, const mpz_t op1, UNIX_ULONG op2);
+ void __gmpz_addmul (mpz_t rop, const mpz_t op1, const mpz_t op2);
+ void __gmpz_addmul_ui (mpz_t rop, const mpz_t op1, UNIX_ULONG op2);
+ void __gmpz_submul_ui (mpz_t rop, const mpz_t op1, UNIX_ULONG op2);
+ void __gmpz_import (mpz_t rop, size_t count, int order, size_t size,
+ int endian, size_t nails, const void *op);
+ void * __gmpz_export (void *rop, size_t *countp, int order,
+ size_t size,
+ int endian, size_t nails, const mpz_t op);
+ size_t __gmpz_sizeinbase (const mpz_t op, int base);
+ void __gmpz_sub (mpz_t rop, const mpz_t op1, const mpz_t op2);
+ void __gmpz_mul (mpz_t rop, const mpz_t op1, const mpz_t op2);
+ void __gmpz_mul_ui (mpz_t rop, const mpz_t op1, UNIX_ULONG op2);
+ int __gmpz_cmp (const mpz_t op1, const mpz_t op2);
+ void __gmpz_powm (mpz_t rop, const mpz_t base, const mpz_t exp, const
+ mpz_t mod);
+ void __gmpz_powm_ui (mpz_t rop, const mpz_t base, UNIX_ULONG exp,
+ const mpz_t mod);
+ void __gmpz_pow_ui (mpz_t rop, const mpz_t base, UNIX_ULONG exp);
+ void __gmpz_sqrt(mpz_t rop, const mpz_t op);
+ void __gmpz_mod (mpz_t r, const mpz_t n, const mpz_t d);
+ void __gmpz_neg (mpz_t rop, const mpz_t op);
+ void __gmpz_abs (mpz_t rop, const mpz_t op);
+ void __gmpz_and (mpz_t rop, const mpz_t op1, const mpz_t op2);
+ void __gmpz_ior (mpz_t rop, const mpz_t op1, const mpz_t op2);
+ void __gmpz_clear (mpz_t x);
+ void __gmpz_tdiv_q_2exp (mpz_t q, const mpz_t n, mp_bitcnt_t b);
+ void __gmpz_fdiv_q (mpz_t q, const mpz_t n, const mpz_t d);
+ void __gmpz_mul_2exp (mpz_t rop, const mpz_t op1, mp_bitcnt_t op2);
+ int __gmpz_tstbit (const mpz_t op, mp_bitcnt_t bit_index);
+ int __gmpz_perfect_square_p (const mpz_t op);
+ int __gmpz_jacobi (const mpz_t a, const mpz_t b);
+ void __gmpz_gcd (mpz_t rop, const mpz_t op1, const mpz_t op2);
+ UNIX_ULONG __gmpz_gcd_ui (mpz_t rop, const mpz_t op1,
+ UNIX_ULONG op2);
+ void __gmpz_lcm (mpz_t rop, const mpz_t op1, const mpz_t op2);
+ int __gmpz_invert (mpz_t rop, const mpz_t op1, const mpz_t op2);
+ int __gmpz_divisible_p (const mpz_t n, const mpz_t d);
+ int __gmpz_divisible_ui_p (const mpz_t n, UNIX_ULONG d);
+ """
+
+if sys.platform == "win32":
+ raise ImportError("Not using GMP on Windows")
+
+lib = load_lib("gmp", gmp_defs)
+implementation = {"library": "gmp", "api": backend}
+
+if hasattr(lib, "__mpir_version"):
+ raise ImportError("MPIR library detected")
+
+# In order to create a function that returns a pointer to
+# a new MPZ structure, we need to break the abstraction
+# and know exactly what ffi backend we have
+if implementation["api"] == "ctypes":
+ from ctypes import Structure, c_int, c_void_p, byref
+
+ class _MPZ(Structure):
+ _fields_ = [('_mp_alloc', c_int),
+ ('_mp_size', c_int),
+ ('_mp_d', c_void_p)]
+
+ def new_mpz():
+ return byref(_MPZ())
+
+else:
+ # We are using CFFI
+ from Cryptodome.Util._raw_api import ffi
+
+ def new_mpz():
+ return ffi.new("MPZ*")
+
+
+# Lazy creation of GMP methods
+class _GMP(object):
+
+ def __getattr__(self, name):
+ if name.startswith("mpz_"):
+ func_name = "__gmpz_" + name[4:]
+ elif name.startswith("gmp_"):
+ func_name = "__gmp_" + name[4:]
+ else:
+ raise AttributeError("Attribute %s is invalid" % name)
+ func = getattr(lib, func_name)
+ setattr(self, name, func)
+ return func
+
+
+_gmp = _GMP()
+
+
+class IntegerGMP(IntegerBase):
+ """A fast, arbitrary precision integer"""
+
+ _zero_mpz_p = new_mpz()
+ _gmp.mpz_init_set_ui(_zero_mpz_p, c_ulong(0))
+
+ def __init__(self, value):
+ """Initialize the integer to the given value."""
+
+ self._mpz_p = new_mpz()
+ self._initialized = False
+
+ if isinstance(value, float):
+ raise ValueError("A floating point type is not a natural number")
+
+ self._initialized = True
+
+ if is_native_int(value):
+ _gmp.mpz_init(self._mpz_p)
+ result = _gmp.gmp_sscanf(tobytes(str(value)), b"%Zd", self._mpz_p)
+ if result != 1:
+ raise ValueError("Error converting '%d'" % value)
+ elif isinstance(value, IntegerGMP):
+ _gmp.mpz_init_set(self._mpz_p, value._mpz_p)
+ else:
+ raise NotImplementedError
+
+ # Conversions
+ def __int__(self):
+ # buf will contain the integer encoded in decimal plus the trailing
+ # zero, and possibly the negative sign.
+ # dig10(x) < log10(x) + 1 = log2(x)/log2(10) + 1 < log2(x)/3 + 1
+ buf_len = _gmp.mpz_sizeinbase(self._mpz_p, 2) // 3 + 3
+ buf = create_string_buffer(buf_len)
+
+ _gmp.gmp_snprintf(buf, c_size_t(buf_len), b"%Zd", self._mpz_p)
+ return int(get_c_string(buf))
+
+ def __str__(self):
+ return str(int(self))
+
+ def __repr__(self):
+ return "Integer(%s)" % str(self)
+
+ # Only Python 2.x
+ def __hex__(self):
+ return hex(int(self))
+
+ # Only Python 3.x
+ def __index__(self):
+ return int(self)
+
+ def to_bytes(self, block_size=0):
+ """Convert the number into a byte string.
+
+ This method encodes the number in network order and prepends
+ as many zero bytes as required. It only works for non-negative
+ values.
+
+ :Parameters:
+ block_size : integer
+ The exact size the output byte string must have.
+ If zero, the string has the minimal length.
+ :Returns:
+ A byte string.
+ :Raise ValueError:
+ If the value is negative or if ``block_size`` is
+ provided and the length of the byte string would exceed it.
+ """
+
+ if self < 0:
+ raise ValueError("Conversion only valid for non-negative numbers")
+
+ buf_len = (_gmp.mpz_sizeinbase(self._mpz_p, 2) + 7) // 8
+ if buf_len > block_size > 0:
+ raise ValueError("Number is too big to convert to byte string"
+ "of prescribed length")
+ buf = create_string_buffer(buf_len)
+
+ _gmp.mpz_export(
+ buf,
+ null_pointer, # Ignore countp
+ 1, # Big endian
+ c_size_t(1), # Each word is 1 byte long
+ 0, # Endianess within a word - not relevant
+ c_size_t(0), # No nails
+ self._mpz_p)
+
+ return b'\x00' * max(0, block_size - buf_len) + get_raw_buffer(buf)
+
+ @staticmethod
+ def from_bytes(byte_string):
+ """Convert a byte string into a number.
+
+ :Parameters:
+ byte_string : byte string
+ The input number, encoded in network order.
+ It can only be non-negative.
+ :Return:
+ The ``Integer`` object carrying the same value as the input.
+ """
+ result = IntegerGMP(0)
+ _gmp.mpz_import(
+ result._mpz_p,
+ c_size_t(len(byte_string)), # Amount of words to read
+ 1, # Big endian
+ c_size_t(1), # Each word is 1 byte long
+ 0, # Endianess within a word - not relevant
+ c_size_t(0), # No nails
+ byte_string)
+ return result
+
+ # Relations
+ def _apply_and_return(self, func, term):
+ if not isinstance(term, IntegerGMP):
+ term = IntegerGMP(term)
+ return func(self._mpz_p, term._mpz_p)
+
+ def __eq__(self, term):
+ if not (isinstance(term, IntegerGMP) or is_native_int(term)):
+ return False
+ return self._apply_and_return(_gmp.mpz_cmp, term) == 0
+
+ def __ne__(self, term):
+ if not (isinstance(term, IntegerGMP) or is_native_int(term)):
+ return True
+ return self._apply_and_return(_gmp.mpz_cmp, term) != 0
+
+ def __lt__(self, term):
+ return self._apply_and_return(_gmp.mpz_cmp, term) < 0
+
+ def __le__(self, term):
+ return self._apply_and_return(_gmp.mpz_cmp, term) <= 0
+
+ def __gt__(self, term):
+ return self._apply_and_return(_gmp.mpz_cmp, term) > 0
+
+ def __ge__(self, term):
+ return self._apply_and_return(_gmp.mpz_cmp, term) >= 0
+
+ def __nonzero__(self):
+ return _gmp.mpz_cmp(self._mpz_p, self._zero_mpz_p) != 0
+ __bool__ = __nonzero__
+
+ def is_negative(self):
+ return _gmp.mpz_cmp(self._mpz_p, self._zero_mpz_p) < 0
+
+ # Arithmetic operations
+ def __add__(self, term):
+ result = IntegerGMP(0)
+ if not isinstance(term, IntegerGMP):
+ try:
+ term = IntegerGMP(term)
+ except NotImplementedError:
+ return NotImplemented
+ _gmp.mpz_add(result._mpz_p,
+ self._mpz_p,
+ term._mpz_p)
+ return result
+
+ def __sub__(self, term):
+ result = IntegerGMP(0)
+ if not isinstance(term, IntegerGMP):
+ try:
+ term = IntegerGMP(term)
+ except NotImplementedError:
+ return NotImplemented
+ _gmp.mpz_sub(result._mpz_p,
+ self._mpz_p,
+ term._mpz_p)
+ return result
+
+ def __mul__(self, term):
+ result = IntegerGMP(0)
+ if not isinstance(term, IntegerGMP):
+ try:
+ term = IntegerGMP(term)
+ except NotImplementedError:
+ return NotImplemented
+ _gmp.mpz_mul(result._mpz_p,
+ self._mpz_p,
+ term._mpz_p)
+ return result
+
+ def __floordiv__(self, divisor):
+ if not isinstance(divisor, IntegerGMP):
+ divisor = IntegerGMP(divisor)
+ if _gmp.mpz_cmp(divisor._mpz_p,
+ self._zero_mpz_p) == 0:
+ raise ZeroDivisionError("Division by zero")
+ result = IntegerGMP(0)
+ _gmp.mpz_fdiv_q(result._mpz_p,
+ self._mpz_p,
+ divisor._mpz_p)
+ return result
+
+ def __mod__(self, divisor):
+ if not isinstance(divisor, IntegerGMP):
+ divisor = IntegerGMP(divisor)
+ comp = _gmp.mpz_cmp(divisor._mpz_p,
+ self._zero_mpz_p)
+ if comp == 0:
+ raise ZeroDivisionError("Division by zero")
+ if comp < 0:
+ raise ValueError("Modulus must be positive")
+ result = IntegerGMP(0)
+ _gmp.mpz_mod(result._mpz_p,
+ self._mpz_p,
+ divisor._mpz_p)
+ return result
+
+ def inplace_pow(self, exponent, modulus=None):
+
+ if modulus is None:
+ if exponent < 0:
+ raise ValueError("Exponent must not be negative")
+
+ # Normal exponentiation
+ if exponent > 256:
+ raise ValueError("Exponent is too big")
+ _gmp.mpz_pow_ui(self._mpz_p,
+ self._mpz_p, # Base
+ c_ulong(int(exponent))
+ )
+ else:
+ # Modular exponentiation
+ if not isinstance(modulus, IntegerGMP):
+ modulus = IntegerGMP(modulus)
+ if not modulus:
+ raise ZeroDivisionError("Division by zero")
+ if modulus.is_negative():
+ raise ValueError("Modulus must be positive")
+ if is_native_int(exponent):
+ if exponent < 0:
+ raise ValueError("Exponent must not be negative")
+ if exponent < 65536:
+ _gmp.mpz_powm_ui(self._mpz_p,
+ self._mpz_p,
+ c_ulong(exponent),
+ modulus._mpz_p)
+ return self
+ exponent = IntegerGMP(exponent)
+ elif exponent.is_negative():
+ raise ValueError("Exponent must not be negative")
+ _gmp.mpz_powm(self._mpz_p,
+ self._mpz_p,
+ exponent._mpz_p,
+ modulus._mpz_p)
+ return self
+
+ def __pow__(self, exponent, modulus=None):
+ result = IntegerGMP(self)
+ return result.inplace_pow(exponent, modulus)
+
+ def __abs__(self):
+ result = IntegerGMP(0)
+ _gmp.mpz_abs(result._mpz_p, self._mpz_p)
+ return result
+
+ def sqrt(self, modulus=None):
+ """Return the largest Integer that does not
+ exceed the square root"""
+
+ if modulus is None:
+ if self < 0:
+ raise ValueError("Square root of negative value")
+ result = IntegerGMP(0)
+ _gmp.mpz_sqrt(result._mpz_p,
+ self._mpz_p)
+ else:
+ if modulus <= 0:
+ raise ValueError("Modulus must be positive")
+ modulus = int(modulus)
+ result = IntegerGMP(self._tonelli_shanks(int(self) % modulus, modulus))
+
+ return result
+
+ def __iadd__(self, term):
+ if is_native_int(term):
+ if 0 <= term < 65536:
+ _gmp.mpz_add_ui(self._mpz_p,
+ self._mpz_p,
+ c_ulong(term))
+ return self
+ if -65535 < term < 0:
+ _gmp.mpz_sub_ui(self._mpz_p,
+ self._mpz_p,
+ c_ulong(-term))
+ return self
+ term = IntegerGMP(term)
+ _gmp.mpz_add(self._mpz_p,
+ self._mpz_p,
+ term._mpz_p)
+ return self
+
+ def __isub__(self, term):
+ if is_native_int(term):
+ if 0 <= term < 65536:
+ _gmp.mpz_sub_ui(self._mpz_p,
+ self._mpz_p,
+ c_ulong(term))
+ return self
+ if -65535 < term < 0:
+ _gmp.mpz_add_ui(self._mpz_p,
+ self._mpz_p,
+ c_ulong(-term))
+ return self
+ term = IntegerGMP(term)
+ _gmp.mpz_sub(self._mpz_p,
+ self._mpz_p,
+ term._mpz_p)
+ return self
+
+ def __imul__(self, term):
+ if is_native_int(term):
+ if 0 <= term < 65536:
+ _gmp.mpz_mul_ui(self._mpz_p,
+ self._mpz_p,
+ c_ulong(term))
+ return self
+ if -65535 < term < 0:
+ _gmp.mpz_mul_ui(self._mpz_p,
+ self._mpz_p,
+ c_ulong(-term))
+ _gmp.mpz_neg(self._mpz_p, self._mpz_p)
+ return self
+ term = IntegerGMP(term)
+ _gmp.mpz_mul(self._mpz_p,
+ self._mpz_p,
+ term._mpz_p)
+ return self
+
+ def __imod__(self, divisor):
+ if not isinstance(divisor, IntegerGMP):
+ divisor = IntegerGMP(divisor)
+ comp = _gmp.mpz_cmp(divisor._mpz_p,
+ divisor._zero_mpz_p)
+ if comp == 0:
+ raise ZeroDivisionError("Division by zero")
+ if comp < 0:
+ raise ValueError("Modulus must be positive")
+ _gmp.mpz_mod(self._mpz_p,
+ self._mpz_p,
+ divisor._mpz_p)
+ return self
+
+ # Boolean/bit operations
+ def __and__(self, term):
+ result = IntegerGMP(0)
+ if not isinstance(term, IntegerGMP):
+ term = IntegerGMP(term)
+ _gmp.mpz_and(result._mpz_p,
+ self._mpz_p,
+ term._mpz_p)
+ return result
+
+ def __or__(self, term):
+ result = IntegerGMP(0)
+ if not isinstance(term, IntegerGMP):
+ term = IntegerGMP(term)
+ _gmp.mpz_ior(result._mpz_p,
+ self._mpz_p,
+ term._mpz_p)
+ return result
+
+ def __rshift__(self, pos):
+ result = IntegerGMP(0)
+ if pos < 0:
+ raise ValueError("negative shift count")
+ if pos > 65536:
+ if self < 0:
+ return -1
+ else:
+ return 0
+ _gmp.mpz_tdiv_q_2exp(result._mpz_p,
+ self._mpz_p,
+ c_ulong(int(pos)))
+ return result
+
+ def __irshift__(self, pos):
+ if pos < 0:
+ raise ValueError("negative shift count")
+ if pos > 65536:
+ if self < 0:
+ return -1
+ else:
+ return 0
+ _gmp.mpz_tdiv_q_2exp(self._mpz_p,
+ self._mpz_p,
+ c_ulong(int(pos)))
+ return self
+
+ def __lshift__(self, pos):
+ result = IntegerGMP(0)
+ if not 0 <= pos < 65536:
+ raise ValueError("Incorrect shift count")
+ _gmp.mpz_mul_2exp(result._mpz_p,
+ self._mpz_p,
+ c_ulong(int(pos)))
+ return result
+
+ def __ilshift__(self, pos):
+ if not 0 <= pos < 65536:
+ raise ValueError("Incorrect shift count")
+ _gmp.mpz_mul_2exp(self._mpz_p,
+ self._mpz_p,
+ c_ulong(int(pos)))
+ return self
+
+ def get_bit(self, n):
+ """Return True if the n-th bit is set to 1.
+ Bit 0 is the least significant."""
+
+ if self < 0:
+ raise ValueError("no bit representation for negative values")
+ if n < 0:
+ raise ValueError("negative bit count")
+ if n > 65536:
+ return 0
+ return bool(_gmp.mpz_tstbit(self._mpz_p,
+ c_ulong(int(n))))
+
+ # Extra
+ def is_odd(self):
+ return _gmp.mpz_tstbit(self._mpz_p, 0) == 1
+
+ def is_even(self):
+ return _gmp.mpz_tstbit(self._mpz_p, 0) == 0
+
+ def size_in_bits(self):
+ """Return the minimum number of bits that can encode the number."""
+
+ if self < 0:
+ raise ValueError("Conversion only valid for non-negative numbers")
+ return _gmp.mpz_sizeinbase(self._mpz_p, 2)
+
+ def size_in_bytes(self):
+ """Return the minimum number of bytes that can encode the number."""
+ return (self.size_in_bits() - 1) // 8 + 1
+
+ def is_perfect_square(self):
+ return _gmp.mpz_perfect_square_p(self._mpz_p) != 0
+
+ def fail_if_divisible_by(self, small_prime):
+ """Raise an exception if the small prime is a divisor."""
+
+ if is_native_int(small_prime):
+ if 0 < small_prime < 65536:
+ if _gmp.mpz_divisible_ui_p(self._mpz_p,
+ c_ulong(small_prime)):
+ raise ValueError("The value is composite")
+ return
+ small_prime = IntegerGMP(small_prime)
+ if _gmp.mpz_divisible_p(self._mpz_p,
+ small_prime._mpz_p):
+ raise ValueError("The value is composite")
+
+ def multiply_accumulate(self, a, b):
+ """Increment the number by the product of a and b."""
+
+ if not isinstance(a, IntegerGMP):
+ a = IntegerGMP(a)
+ if is_native_int(b):
+ if 0 < b < 65536:
+ _gmp.mpz_addmul_ui(self._mpz_p,
+ a._mpz_p,
+ c_ulong(b))
+ return self
+ if -65535 < b < 0:
+ _gmp.mpz_submul_ui(self._mpz_p,
+ a._mpz_p,
+ c_ulong(-b))
+ return self
+ b = IntegerGMP(b)
+ _gmp.mpz_addmul(self._mpz_p,
+ a._mpz_p,
+ b._mpz_p)
+ return self
+
+ def set(self, source):
+ """Set the Integer to have the given value"""
+
+ if not isinstance(source, IntegerGMP):
+ source = IntegerGMP(source)
+ _gmp.mpz_set(self._mpz_p,
+ source._mpz_p)
+ return self
+
+ def inplace_inverse(self, modulus):
+ """Compute the inverse of this number in the ring of
+ modulo integers.
+
+ Raise an exception if no inverse exists.
+ """
+
+ if not isinstance(modulus, IntegerGMP):
+ modulus = IntegerGMP(modulus)
+
+ comp = _gmp.mpz_cmp(modulus._mpz_p,
+ self._zero_mpz_p)
+ if comp == 0:
+ raise ZeroDivisionError("Modulus cannot be zero")
+ if comp < 0:
+ raise ValueError("Modulus must be positive")
+
+ result = _gmp.mpz_invert(self._mpz_p,
+ self._mpz_p,
+ modulus._mpz_p)
+ if not result:
+ raise ValueError("No inverse value can be computed")
+ return self
+
+ def inverse(self, modulus):
+ result = IntegerGMP(self)
+ result.inplace_inverse(modulus)
+ return result
+
+ def gcd(self, term):
+ """Compute the greatest common denominator between this
+ number and another term."""
+
+ result = IntegerGMP(0)
+ if is_native_int(term):
+ if 0 < term < 65535:
+ _gmp.mpz_gcd_ui(result._mpz_p,
+ self._mpz_p,
+ c_ulong(term))
+ return result
+ term = IntegerGMP(term)
+ _gmp.mpz_gcd(result._mpz_p, self._mpz_p, term._mpz_p)
+ return result
+
+ def lcm(self, term):
+ """Compute the least common multiplier between this
+ number and another term."""
+
+ result = IntegerGMP(0)
+ if not isinstance(term, IntegerGMP):
+ term = IntegerGMP(term)
+ _gmp.mpz_lcm(result._mpz_p, self._mpz_p, term._mpz_p)
+ return result
+
+ @staticmethod
+ def jacobi_symbol(a, n):
+ """Compute the Jacobi symbol"""
+
+ if not isinstance(a, IntegerGMP):
+ a = IntegerGMP(a)
+ if not isinstance(n, IntegerGMP):
+ n = IntegerGMP(n)
+ if n <= 0 or n.is_even():
+ raise ValueError("n must be positive even for the Jacobi symbol")
+ return _gmp.mpz_jacobi(a._mpz_p, n._mpz_p)
+
+ # Clean-up
+ def __del__(self):
+
+ try:
+ if self._mpz_p is not None:
+ if self._initialized:
+ _gmp.mpz_clear(self._mpz_p)
+
+ self._mpz_p = None
+ except AttributeError:
+ pass
diff --git a/frozen_deps/Cryptodome/Math/_IntegerGMP.pyi b/frozen_deps/Cryptodome/Math/_IntegerGMP.pyi
new file mode 100644
index 0000000..2181b47
--- /dev/null
+++ b/frozen_deps/Cryptodome/Math/_IntegerGMP.pyi
@@ -0,0 +1,3 @@
+from ._IntegerBase import IntegerBase
+class IntegerGMP(IntegerBase):
+ pass
diff --git a/frozen_deps/Cryptodome/Math/_IntegerNative.py b/frozen_deps/Cryptodome/Math/_IntegerNative.py
new file mode 100644
index 0000000..896107f
--- /dev/null
+++ b/frozen_deps/Cryptodome/Math/_IntegerNative.py
@@ -0,0 +1,380 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+from ._IntegerBase import IntegerBase
+
+from Cryptodome.Util.number import long_to_bytes, bytes_to_long
+
+
+class IntegerNative(IntegerBase):
+ """A class to model a natural integer (including zero)"""
+
+ def __init__(self, value):
+ if isinstance(value, float):
+ raise ValueError("A floating point type is not a natural number")
+ try:
+ self._value = value._value
+ except AttributeError:
+ self._value = value
+
+ # Conversions
+ def __int__(self):
+ return self._value
+
+ def __str__(self):
+ return str(int(self))
+
+ def __repr__(self):
+ return "Integer(%s)" % str(self)
+
+ # Only Python 2.x
+ def __hex__(self):
+ return hex(self._value)
+
+ # Only Python 3.x
+ def __index__(self):
+ return int(self._value)
+
+ def to_bytes(self, block_size=0):
+ if self._value < 0:
+ raise ValueError("Conversion only valid for non-negative numbers")
+ result = long_to_bytes(self._value, block_size)
+ if len(result) > block_size > 0:
+ raise ValueError("Value too large to encode")
+ return result
+
+ @classmethod
+ def from_bytes(cls, byte_string):
+ return cls(bytes_to_long(byte_string))
+
+ # Relations
+ def __eq__(self, term):
+ if term is None:
+ return False
+ return self._value == int(term)
+
+ def __ne__(self, term):
+ return not self.__eq__(term)
+
+ def __lt__(self, term):
+ return self._value < int(term)
+
+ def __le__(self, term):
+ return self.__lt__(term) or self.__eq__(term)
+
+ def __gt__(self, term):
+ return not self.__le__(term)
+
+ def __ge__(self, term):
+ return not self.__lt__(term)
+
+ def __nonzero__(self):
+ return self._value != 0
+ __bool__ = __nonzero__
+
+ def is_negative(self):
+ return self._value < 0
+
+ # Arithmetic operations
+ def __add__(self, term):
+ try:
+ return self.__class__(self._value + int(term))
+ except (ValueError, AttributeError, TypeError):
+ return NotImplemented
+
+ def __sub__(self, term):
+ try:
+ return self.__class__(self._value - int(term))
+ except (ValueError, AttributeError, TypeError):
+ return NotImplemented
+
+ def __mul__(self, factor):
+ try:
+ return self.__class__(self._value * int(factor))
+ except (ValueError, AttributeError, TypeError):
+ return NotImplemented
+
+ def __floordiv__(self, divisor):
+ return self.__class__(self._value // int(divisor))
+
+ def __mod__(self, divisor):
+ divisor_value = int(divisor)
+ if divisor_value < 0:
+ raise ValueError("Modulus must be positive")
+ return self.__class__(self._value % divisor_value)
+
+ def inplace_pow(self, exponent, modulus=None):
+ exp_value = int(exponent)
+ if exp_value < 0:
+ raise ValueError("Exponent must not be negative")
+
+ if modulus is not None:
+ mod_value = int(modulus)
+ if mod_value < 0:
+ raise ValueError("Modulus must be positive")
+ if mod_value == 0:
+ raise ZeroDivisionError("Modulus cannot be zero")
+ else:
+ mod_value = None
+ self._value = pow(self._value, exp_value, mod_value)
+ return self
+
+ def __pow__(self, exponent, modulus=None):
+ result = self.__class__(self)
+ return result.inplace_pow(exponent, modulus)
+
+ def __abs__(self):
+ return abs(self._value)
+
+ def sqrt(self, modulus=None):
+
+ value = self._value
+ if modulus is None:
+ if value < 0:
+ raise ValueError("Square root of negative value")
+ # http://stackoverflow.com/questions/15390807/integer-square-root-in-python
+
+ x = value
+ y = (x + 1) // 2
+ while y < x:
+ x = y
+ y = (x + value // x) // 2
+ result = x
+ else:
+ if modulus <= 0:
+ raise ValueError("Modulus must be positive")
+ result = self._tonelli_shanks(self % modulus, modulus)
+
+ return self.__class__(result)
+
+ def __iadd__(self, term):
+ self._value += int(term)
+ return self
+
+ def __isub__(self, term):
+ self._value -= int(term)
+ return self
+
+ def __imul__(self, term):
+ self._value *= int(term)
+ return self
+
+ def __imod__(self, term):
+ modulus = int(term)
+ if modulus == 0:
+ raise ZeroDivisionError("Division by zero")
+ if modulus < 0:
+ raise ValueError("Modulus must be positive")
+ self._value %= modulus
+ return self
+
+ # Boolean/bit operations
+ def __and__(self, term):
+ return self.__class__(self._value & int(term))
+
+ def __or__(self, term):
+ return self.__class__(self._value | int(term))
+
+ def __rshift__(self, pos):
+ try:
+ return self.__class__(self._value >> int(pos))
+ except OverflowError:
+ if self._value >= 0:
+ return 0
+ else:
+ return -1
+
+ def __irshift__(self, pos):
+ try:
+ self._value >>= int(pos)
+ except OverflowError:
+ if self._value >= 0:
+ return 0
+ else:
+ return -1
+ return self
+
+ def __lshift__(self, pos):
+ try:
+ return self.__class__(self._value << int(pos))
+ except OverflowError:
+ raise ValueError("Incorrect shift count")
+
+ def __ilshift__(self, pos):
+ try:
+ self._value <<= int(pos)
+ except OverflowError:
+ raise ValueError("Incorrect shift count")
+ return self
+
+ def get_bit(self, n):
+ if self._value < 0:
+ raise ValueError("no bit representation for negative values")
+ try:
+ try:
+ result = (self._value >> n._value) & 1
+ if n._value < 0:
+ raise ValueError("negative bit count")
+ except AttributeError:
+ result = (self._value >> n) & 1
+ if n < 0:
+ raise ValueError("negative bit count")
+ except OverflowError:
+ result = 0
+ return result
+
+ # Extra
+ def is_odd(self):
+ return (self._value & 1) == 1
+
+ def is_even(self):
+ return (self._value & 1) == 0
+
+ def size_in_bits(self):
+
+ if self._value < 0:
+ raise ValueError("Conversion only valid for non-negative numbers")
+
+ if self._value == 0:
+ return 1
+
+ bit_size = 0
+ tmp = self._value
+ while tmp:
+ tmp >>= 1
+ bit_size += 1
+
+ return bit_size
+
+ def size_in_bytes(self):
+ return (self.size_in_bits() - 1) // 8 + 1
+
+ def is_perfect_square(self):
+ if self._value < 0:
+ return False
+ if self._value in (0, 1):
+ return True
+
+ x = self._value // 2
+ square_x = x ** 2
+
+ while square_x > self._value:
+ x = (square_x + self._value) // (2 * x)
+ square_x = x ** 2
+
+ return self._value == x ** 2
+
+ def fail_if_divisible_by(self, small_prime):
+ if (self._value % int(small_prime)) == 0:
+ raise ValueError("Value is composite")
+
+ def multiply_accumulate(self, a, b):
+ self._value += int(a) * int(b)
+ return self
+
+ def set(self, source):
+ self._value = int(source)
+
+ def inplace_inverse(self, modulus):
+ modulus = int(modulus)
+ if modulus == 0:
+ raise ZeroDivisionError("Modulus cannot be zero")
+ if modulus < 0:
+ raise ValueError("Modulus cannot be negative")
+ r_p, r_n = self._value, modulus
+ s_p, s_n = 1, 0
+ while r_n > 0:
+ q = r_p // r_n
+ r_p, r_n = r_n, r_p - q * r_n
+ s_p, s_n = s_n, s_p - q * s_n
+ if r_p != 1:
+ raise ValueError("No inverse value can be computed" + str(r_p))
+ while s_p < 0:
+ s_p += modulus
+ self._value = s_p
+ return self
+
+ def inverse(self, modulus):
+ result = self.__class__(self)
+ result.inplace_inverse(modulus)
+ return result
+
+ def gcd(self, term):
+ r_p, r_n = abs(self._value), abs(int(term))
+ while r_n > 0:
+ q = r_p // r_n
+ r_p, r_n = r_n, r_p - q * r_n
+ return self.__class__(r_p)
+
+ def lcm(self, term):
+ term = int(term)
+ if self._value == 0 or term == 0:
+ return self.__class__(0)
+ return self.__class__(abs((self._value * term) // self.gcd(term)._value))
+
+ @staticmethod
+ def jacobi_symbol(a, n):
+ a = int(a)
+ n = int(n)
+
+ if n <= 0:
+ raise ValueError("n must be a positive integer")
+
+ if (n & 1) == 0:
+ raise ValueError("n must be even for the Jacobi symbol")
+
+ # Step 1
+ a = a % n
+ # Step 2
+ if a == 1 or n == 1:
+ return 1
+ # Step 3
+ if a == 0:
+ return 0
+ # Step 4
+ e = 0
+ a1 = a
+ while (a1 & 1) == 0:
+ a1 >>= 1
+ e += 1
+ # Step 5
+ if (e & 1) == 0:
+ s = 1
+ elif n % 8 in (1, 7):
+ s = 1
+ else:
+ s = -1
+ # Step 6
+ if n % 4 == 3 and a1 % 4 == 3:
+ s = -s
+ # Step 7
+ n1 = n % a1
+ # Step 8
+ return s * IntegerNative.jacobi_symbol(n1, a1)
diff --git a/frozen_deps/Cryptodome/Math/_IntegerNative.pyi b/frozen_deps/Cryptodome/Math/_IntegerNative.pyi
new file mode 100644
index 0000000..3f65a39
--- /dev/null
+++ b/frozen_deps/Cryptodome/Math/_IntegerNative.pyi
@@ -0,0 +1,3 @@
+from ._IntegerBase import IntegerBase
+class IntegerNative(IntegerBase):
+ pass
diff --git a/frozen_deps/Cryptodome/Math/__init__.py b/frozen_deps/Cryptodome/Math/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/frozen_deps/Cryptodome/Math/__init__.py
diff --git a/frozen_deps/Cryptodome/Math/_modexp.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Math/_modexp.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..9b8cd0a
--- /dev/null
+++ b/frozen_deps/Cryptodome/Math/_modexp.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Protocol/KDF.py b/frozen_deps/Cryptodome/Protocol/KDF.py
new file mode 100644
index 0000000..4baa276
--- /dev/null
+++ b/frozen_deps/Cryptodome/Protocol/KDF.py
@@ -0,0 +1,574 @@
+# coding=utf-8
+#
+# KDF.py : a collection of Key Derivation Functions
+#
+# Part of the Python Cryptography Toolkit
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+import re
+import struct
+from functools import reduce
+
+from Cryptodome.Util.py3compat import (tobytes, bord, _copy_bytes, iter_range,
+ tostr, bchr, bstr)
+
+from Cryptodome.Hash import SHA1, SHA256, HMAC, CMAC, BLAKE2s
+from Cryptodome.Util.strxor import strxor
+from Cryptodome.Random import get_random_bytes
+from Cryptodome.Util.number import size as bit_size, long_to_bytes, bytes_to_long
+
+from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib,
+ create_string_buffer,
+ get_raw_buffer, c_size_t)
+
+_raw_salsa20_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._Salsa20",
+ """
+ int Salsa20_8_core(const uint8_t *x, const uint8_t *y,
+ uint8_t *out);
+ """)
+
+_raw_scrypt_lib = load_pycryptodome_raw_lib("Cryptodome.Protocol._scrypt",
+ """
+ typedef int (core_t)(const uint8_t [64], const uint8_t [64], uint8_t [64]);
+ int scryptROMix(const uint8_t *data_in, uint8_t *data_out,
+ size_t data_len, unsigned N, core_t *core);
+ """)
+
+
+def PBKDF1(password, salt, dkLen, count=1000, hashAlgo=None):
+ """Derive one key from a password (or passphrase).
+
+ This function performs key derivation according to an old version of
+ the PKCS#5 standard (v1.5) or `RFC2898
+ <https://www.ietf.org/rfc/rfc2898.txt>`_.
+
+ Args:
+ password (string):
+ The secret password to generate the key from.
+ salt (byte string):
+ An 8 byte string to use for better protection from dictionary attacks.
+ This value does not need to be kept secret, but it should be randomly
+ chosen for each derivation.
+ dkLen (integer):
+ The length of the desired key. The default is 16 bytes, suitable for
+ instance for :mod:`Cryptodome.Cipher.AES`.
+ count (integer):
+ The number of iterations to carry out. The recommendation is 1000 or
+ more.
+ hashAlgo (module):
+ The hash algorithm to use, as a module or an object from the :mod:`Cryptodome.Hash` package.
+ The digest length must be no shorter than ``dkLen``.
+ The default algorithm is :mod:`Cryptodome.Hash.SHA1`.
+
+ Return:
+ A byte string of length ``dkLen`` that can be used as key.
+ """
+
+ if not hashAlgo:
+ hashAlgo = SHA1
+ password = tobytes(password)
+ pHash = hashAlgo.new(password+salt)
+ digest = pHash.digest_size
+ if dkLen > digest:
+ raise TypeError("Selected hash algorithm has a too short digest (%d bytes)." % digest)
+ if len(salt) != 8:
+ raise ValueError("Salt is not 8 bytes long (%d bytes instead)." % len(salt))
+ for i in iter_range(count-1):
+ pHash = pHash.new(pHash.digest())
+ return pHash.digest()[:dkLen]
+
+
+def PBKDF2(password, salt, dkLen=16, count=1000, prf=None, hmac_hash_module=None):
+ """Derive one or more keys from a password (or passphrase).
+
+ This function performs key derivation according to the PKCS#5 standard (v2.0).
+
+ Args:
+ password (string or byte string):
+ The secret password to generate the key from.
+ salt (string or byte string):
+ A (byte) string to use for better protection from dictionary attacks.
+ This value does not need to be kept secret, but it should be randomly
+ chosen for each derivation. It is recommended to use at least 16 bytes.
+ dkLen (integer):
+ The cumulative length of the keys to produce.
+
+ Due to a flaw in the PBKDF2 design, you should not request more bytes
+ than the ``prf`` can output. For instance, ``dkLen`` should not exceed
+ 20 bytes in combination with ``HMAC-SHA1``.
+ count (integer):
+ The number of iterations to carry out. The higher the value, the slower
+ and the more secure the function becomes.
+
+ You should find the maximum number of iterations that keeps the
+ key derivation still acceptable on the slowest hardware you must support.
+
+ Although the default value is 1000, **it is recommended to use at least
+ 1000000 (1 million) iterations**.
+ prf (callable):
+ A pseudorandom function. It must be a function that returns a
+ pseudorandom byte string from two parameters: a secret and a salt.
+ The slower the algorithm, the more secure the derivation function.
+ If not specified, **HMAC-SHA1** is used.
+ hmac_hash_module (module):
+ A module from ``Cryptodome.Hash`` implementing a Merkle-Damgard cryptographic
+ hash, which PBKDF2 must use in combination with HMAC.
+ This parameter is mutually exclusive with ``prf``.
+
+ Return:
+ A byte string of length ``dkLen`` that can be used as key material.
+ If you want multiple keys, just break up this string into segments of the desired length.
+ """
+
+ password = tobytes(password)
+ salt = tobytes(salt)
+
+ if prf and hmac_hash_module:
+ raise ValueError("'prf' and 'hmac_hash_module' are mutually exlusive")
+
+ if prf is None and hmac_hash_module is None:
+ hmac_hash_module = SHA1
+
+ if prf or not hasattr(hmac_hash_module, "_pbkdf2_hmac_assist"):
+ # Generic (and slow) implementation
+
+ if prf is None:
+ prf = lambda p,s: HMAC.new(p, s, hmac_hash_module).digest()
+
+ def link(s):
+ s[0], s[1] = s[1], prf(password, s[1])
+ return s[0]
+
+ key = b''
+ i = 1
+ while len(key) < dkLen:
+ s = [ prf(password, salt + struct.pack(">I", i)) ] * 2
+ key += reduce(strxor, (link(s) for j in range(count)) )
+ i += 1
+
+ else:
+ # Optimized implementation
+ key = b''
+ i = 1
+ while len(key)<dkLen:
+ base = HMAC.new(password, b"", hmac_hash_module)
+ first_digest = base.copy().update(salt + struct.pack(">I", i)).digest()
+ key += base._pbkdf2_hmac_assist(first_digest, count)
+ i += 1
+
+ return key[:dkLen]
+
+
+class _S2V(object):
+ """String-to-vector PRF as defined in `RFC5297`_.
+
+ This class implements a pseudorandom function family
+ based on CMAC that takes as input a vector of strings.
+
+ .. _RFC5297: http://tools.ietf.org/html/rfc5297
+ """
+
+ def __init__(self, key, ciphermod, cipher_params=None):
+ """Initialize the S2V PRF.
+
+ :Parameters:
+ key : byte string
+ A secret that can be used as key for CMACs
+ based on ciphers from ``ciphermod``.
+ ciphermod : module
+ A block cipher module from `Cryptodome.Cipher`.
+ cipher_params : dictionary
+ A set of extra parameters to use to create a cipher instance.
+ """
+
+ self._key = _copy_bytes(None, None, key)
+ self._ciphermod = ciphermod
+ self._last_string = self._cache = b'\x00' * ciphermod.block_size
+
+ # Max number of update() call we can process
+ self._n_updates = ciphermod.block_size * 8 - 1
+
+ if cipher_params is None:
+ self._cipher_params = {}
+ else:
+ self._cipher_params = dict(cipher_params)
+
+ @staticmethod
+ def new(key, ciphermod):
+ """Create a new S2V PRF.
+
+ :Parameters:
+ key : byte string
+ A secret that can be used as key for CMACs
+ based on ciphers from ``ciphermod``.
+ ciphermod : module
+ A block cipher module from `Cryptodome.Cipher`.
+ """
+ return _S2V(key, ciphermod)
+
+ def _double(self, bs):
+ doubled = bytes_to_long(bs)<<1
+ if bord(bs[0]) & 0x80:
+ doubled ^= 0x87
+ return long_to_bytes(doubled, len(bs))[-len(bs):]
+
+ def update(self, item):
+ """Pass the next component of the vector.
+
+ The maximum number of components you can pass is equal to the block
+ length of the cipher (in bits) minus 1.
+
+ :Parameters:
+ item : byte string
+ The next component of the vector.
+ :Raise TypeError: when the limit on the number of components has been reached.
+ """
+
+ if self._n_updates == 0:
+ raise TypeError("Too many components passed to S2V")
+ self._n_updates -= 1
+
+ mac = CMAC.new(self._key,
+ msg=self._last_string,
+ ciphermod=self._ciphermod,
+ cipher_params=self._cipher_params)
+ self._cache = strxor(self._double(self._cache), mac.digest())
+ self._last_string = _copy_bytes(None, None, item)
+
+ def derive(self):
+ """"Derive a secret from the vector of components.
+
+ :Return: a byte string, as long as the block length of the cipher.
+ """
+
+ if len(self._last_string) >= 16:
+ # xorend
+ final = self._last_string[:-16] + strxor(self._last_string[-16:], self._cache)
+ else:
+ # zero-pad & xor
+ padded = (self._last_string + b'\x80' + b'\x00' * 15)[:16]
+ final = strxor(padded, self._double(self._cache))
+ mac = CMAC.new(self._key,
+ msg=final,
+ ciphermod=self._ciphermod,
+ cipher_params=self._cipher_params)
+ return mac.digest()
+
+
+def HKDF(master, key_len, salt, hashmod, num_keys=1, context=None):
+ """Derive one or more keys from a master secret using
+ the HMAC-based KDF defined in RFC5869_.
+
+ Args:
+ master (byte string):
+ The unguessable value used by the KDF to generate the other keys.
+ It must be a high-entropy secret, though not necessarily uniform.
+ It must not be a password.
+ salt (byte string):
+ A non-secret, reusable value that strengthens the randomness
+ extraction step.
+ Ideally, it is as long as the digest size of the chosen hash.
+ If empty, a string of zeroes in used.
+ key_len (integer):
+ The length in bytes of every derived key.
+ hashmod (module):
+ A cryptographic hash algorithm from :mod:`Cryptodome.Hash`.
+ :mod:`Cryptodome.Hash.SHA512` is a good choice.
+ num_keys (integer):
+ The number of keys to derive. Every key is :data:`key_len` bytes long.
+ The maximum cumulative length of all keys is
+ 255 times the digest size.
+ context (byte string):
+ Optional identifier describing what the keys are used for.
+
+ Return:
+ A byte string or a tuple of byte strings.
+
+ .. _RFC5869: http://tools.ietf.org/html/rfc5869
+ """
+
+ output_len = key_len * num_keys
+ if output_len > (255 * hashmod.digest_size):
+ raise ValueError("Too much secret data to derive")
+ if not salt:
+ salt = b'\x00' * hashmod.digest_size
+ if context is None:
+ context = b""
+
+ # Step 1: extract
+ hmac = HMAC.new(salt, master, digestmod=hashmod)
+ prk = hmac.digest()
+
+ # Step 2: expand
+ t = [ b"" ]
+ n = 1
+ tlen = 0
+ while tlen < output_len:
+ hmac = HMAC.new(prk, t[-1] + context + struct.pack('B', n), digestmod=hashmod)
+ t.append(hmac.digest())
+ tlen += hashmod.digest_size
+ n += 1
+ derived_output = b"".join(t)
+ if num_keys == 1:
+ return derived_output[:key_len]
+ kol = [derived_output[idx:idx + key_len]
+ for idx in iter_range(0, output_len, key_len)]
+ return list(kol[:num_keys])
+
+
+
+def scrypt(password, salt, key_len, N, r, p, num_keys=1):
+ """Derive one or more keys from a passphrase.
+
+ Args:
+ password (string):
+ The secret pass phrase to generate the keys from.
+ salt (string):
+ A string to use for better protection from dictionary attacks.
+ This value does not need to be kept secret,
+ but it should be randomly chosen for each derivation.
+ It is recommended to be at least 16 bytes long.
+ key_len (integer):
+ The length in bytes of every derived key.
+ N (integer):
+ CPU/Memory cost parameter. It must be a power of 2 and less
+ than :math:`2^{32}`.
+ r (integer):
+ Block size parameter.
+ p (integer):
+ Parallelization parameter.
+ It must be no greater than :math:`(2^{32}-1)/(4r)`.
+ num_keys (integer):
+ The number of keys to derive. Every key is :data:`key_len` bytes long.
+ By default, only 1 key is generated.
+ The maximum cumulative length of all keys is :math:`(2^{32}-1)*32`
+ (that is, 128TB).
+
+ A good choice of parameters *(N, r , p)* was suggested
+ by Colin Percival in his `presentation in 2009`__:
+
+ - *( 2¹⁴, 8, 1 )* for interactive logins (≤100ms)
+ - *( 2²⁰, 8, 1 )* for file encryption (≤5s)
+
+ Return:
+ A byte string or a tuple of byte strings.
+
+ .. __: http://www.tarsnap.com/scrypt/scrypt-slides.pdf
+ """
+
+ if 2 ** (bit_size(N) - 1) != N:
+ raise ValueError("N must be a power of 2")
+ if N >= 2 ** 32:
+ raise ValueError("N is too big")
+ if p > ((2 ** 32 - 1) * 32) // (128 * r):
+ raise ValueError("p or r are too big")
+
+ prf_hmac_sha256 = lambda p, s: HMAC.new(p, s, SHA256).digest()
+
+ stage_1 = PBKDF2(password, salt, p * 128 * r, 1, prf=prf_hmac_sha256)
+
+ scryptROMix = _raw_scrypt_lib.scryptROMix
+ core = _raw_salsa20_lib.Salsa20_8_core
+
+ # Parallelize into p flows
+ data_out = []
+ for flow in iter_range(p):
+ idx = flow * 128 * r
+ buffer_out = create_string_buffer(128 * r)
+ result = scryptROMix(stage_1[idx : idx + 128 * r],
+ buffer_out,
+ c_size_t(128 * r),
+ N,
+ core)
+ if result:
+ raise ValueError("Error %X while running scrypt" % result)
+ data_out += [ get_raw_buffer(buffer_out) ]
+
+ dk = PBKDF2(password,
+ b"".join(data_out),
+ key_len * num_keys, 1,
+ prf=prf_hmac_sha256)
+
+ if num_keys == 1:
+ return dk
+
+ kol = [dk[idx:idx + key_len]
+ for idx in iter_range(0, key_len * num_keys, key_len)]
+ return kol
+
+
+def _bcrypt_encode(data):
+ s = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+
+ bits = []
+ for c in data:
+ bits_c = bin(bord(c))[2:].zfill(8)
+ bits.append(bstr(bits_c))
+ bits = b"".join(bits)
+
+ bits6 = [ bits[idx:idx+6] for idx in range(0, len(bits), 6) ]
+
+ result = []
+ for g in bits6[:-1]:
+ idx = int(g, 2)
+ result.append(s[idx])
+
+ g = bits6[-1]
+ idx = int(g, 2) << (6 - len(g))
+ result.append(s[idx])
+ result = "".join(result)
+
+ return tobytes(result)
+
+
+def _bcrypt_decode(data):
+ s = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+
+ bits = []
+ for c in tostr(data):
+ idx = s.find(c)
+ bits6 = bin(idx)[2:].zfill(6)
+ bits.append(bits6)
+ bits = "".join(bits)
+
+ modulo4 = len(data) % 4
+ if modulo4 == 1:
+ raise ValueError("Incorrect length")
+ elif modulo4 == 2:
+ bits = bits[:-4]
+ elif modulo4 == 3:
+ bits = bits[:-2]
+
+ bits8 = [ bits[idx:idx+8] for idx in range(0, len(bits), 8) ]
+
+ result = []
+ for g in bits8:
+ result.append(bchr(int(g, 2)))
+ result = b"".join(result)
+
+ return result
+
+
+def _bcrypt_hash(password, cost, salt, constant, invert):
+ from Cryptodome.Cipher import _EKSBlowfish
+
+ if len(password) > 72:
+ raise ValueError("The password is too long. It must be 72 bytes at most.")
+
+ if not (4 <= cost <= 31):
+ raise ValueError("bcrypt cost factor must be in the range 4..31")
+
+ cipher = _EKSBlowfish.new(password, _EKSBlowfish.MODE_ECB, salt, cost, invert)
+ ctext = constant
+ for _ in range(64):
+ ctext = cipher.encrypt(ctext)
+ return ctext
+
+
+def bcrypt(password, cost, salt=None):
+ """Hash a password into a key, using the OpenBSD bcrypt protocol.
+
+ Args:
+ password (byte string or string):
+ The secret password or pass phrase.
+ It must be at most 72 bytes long.
+ It must not contain the zero byte.
+ Unicode strings will be encoded as UTF-8.
+ cost (integer):
+ The exponential factor that makes it slower to compute the hash.
+ It must be in the range 4 to 31.
+ A value of at least 12 is recommended.
+ salt (byte string):
+ Optional. Random byte string to thwarts dictionary and rainbow table
+ attacks. It must be 16 bytes long.
+ If not passed, a random value is generated.
+
+ Return (byte string):
+ The bcrypt hash
+
+ Raises:
+ ValueError: if password is longer than 72 bytes or if it contains the zero byte
+
+ """
+
+ password = tobytes(password, "utf-8")
+
+ if password.find(bchr(0)[0]) != -1:
+ raise ValueError("The password contains the zero byte")
+
+ if len(password) < 72:
+ password += b"\x00"
+
+ if salt is None:
+ salt = get_random_bytes(16)
+ if len(salt) != 16:
+ raise ValueError("bcrypt salt must be 16 bytes long")
+
+ ctext = _bcrypt_hash(password, cost, salt, b"OrpheanBeholderScryDoubt", True)
+
+ cost_enc = b"$" + bstr(str(cost).zfill(2))
+ salt_enc = b"$" + _bcrypt_encode(salt)
+ hash_enc = _bcrypt_encode(ctext[:-1]) # only use 23 bytes, not 24
+ return b"$2a" + cost_enc + salt_enc + hash_enc
+
+
+def bcrypt_check(password, bcrypt_hash):
+ """Verify if the provided password matches the given bcrypt hash.
+
+ Args:
+ password (byte string or string):
+ The secret password or pass phrase to test.
+ It must be at most 72 bytes long.
+ It must not contain the zero byte.
+ Unicode strings will be encoded as UTF-8.
+ bcrypt_hash (byte string, bytearray):
+ The reference bcrypt hash the password needs to be checked against.
+
+ Raises:
+ ValueError: if the password does not match
+ """
+
+ bcrypt_hash = tobytes(bcrypt_hash)
+
+ if len(bcrypt_hash) != 60:
+ raise ValueError("Incorrect length of the bcrypt hash: %d bytes instead of 60" % len(bcrypt_hash))
+
+ if bcrypt_hash[:4] != b'$2a$':
+ raise ValueError("Unsupported prefix")
+
+ p = re.compile(br'\$2a\$([0-9][0-9])\$([A-Za-z0-9./]{22,22})([A-Za-z0-9./]{31,31})')
+ r = p.match(bcrypt_hash)
+ if not r:
+ raise ValueError("Incorrect bcrypt hash format")
+
+ cost = int(r.group(1))
+ if not (4 <= cost <= 31):
+ raise ValueError("Incorrect cost")
+
+ salt = _bcrypt_decode(r.group(2))
+
+ bcrypt_hash2 = bcrypt(password, cost, salt)
+
+ secret = get_random_bytes(16)
+
+ mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=bcrypt_hash).digest()
+ mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=bcrypt_hash2).digest()
+ if mac1 != mac2:
+ raise ValueError("Incorrect bcrypt hash")
diff --git a/frozen_deps/Cryptodome/Protocol/KDF.pyi b/frozen_deps/Cryptodome/Protocol/KDF.pyi
new file mode 100644
index 0000000..fb004bf
--- /dev/null
+++ b/frozen_deps/Cryptodome/Protocol/KDF.pyi
@@ -0,0 +1,24 @@
+from types import ModuleType
+from typing import Optional, Callable, Tuple, Union, Dict, Any
+
+RNG = Callable[[int], bytes]
+
+def PBKDF1(password: str, salt: bytes, dkLen: int, count: Optional[int]=1000, hashAlgo: Optional[ModuleType]=None) -> bytes: ...
+def PBKDF2(password: str, salt: bytes, dkLen: Optional[int]=16, count: Optional[int]=1000, prf: Optional[RNG]=None, hmac_hash_module: Optional[ModuleType]=None) -> bytes: ...
+
+class _S2V(object):
+ def __init__(self, key: bytes, ciphermod: ModuleType, cipher_params: Optional[Dict[Any, Any]]=None) -> None: ...
+
+ @staticmethod
+ def new(key: bytes, ciphermod: ModuleType) -> None: ...
+ def update(self, item: bytes) -> None: ...
+ def derive(self) -> bytes: ...
+
+def HKDF(master: bytes, key_len: int, salt: bytes, hashmod: ModuleType, num_keys: Optional[int]=1, context: Optional[bytes]=None) -> Union[bytes, Tuple[bytes, ...]]: ...
+
+def scrypt(password: str, salt: str, key_len: int, N: int, r: int, p: int, num_keys: Optional[int]=1) -> Union[bytes, Tuple[bytes, ...]]: ...
+
+def _bcrypt_decode(data: bytes) -> bytes: ...
+def _bcrypt_hash(password:bytes , cost: int, salt: bytes, constant:bytes, invert:bool) -> bytes: ...
+def bcrypt(password: Union[bytes, str], cost: int, salt: Optional[bytes]=None) -> bytes: ...
+def bcrypt_check(password: Union[bytes, str], bcrypt_hash: Union[bytes, bytearray, str]) -> None: ...
diff --git a/frozen_deps/Cryptodome/Protocol/SecretSharing.py b/frozen_deps/Cryptodome/Protocol/SecretSharing.py
new file mode 100644
index 0000000..6fdc9b4
--- /dev/null
+++ b/frozen_deps/Cryptodome/Protocol/SecretSharing.py
@@ -0,0 +1,278 @@
+#
+# SecretSharing.py : distribute a secret amongst a group of participants
+#
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# 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_native_int
+from Cryptodome.Util import number
+from Cryptodome.Util.number import long_to_bytes, bytes_to_long
+from Cryptodome.Random import get_random_bytes as rng
+
+
+def _mult_gf2(f1, f2):
+ """Multiply two polynomials in GF(2)"""
+
+ # Ensure f2 is the smallest
+ if f2 > f1:
+ f1, f2 = f2, f1
+ z = 0
+ while f2:
+ if f2 & 1:
+ z ^= f1
+ f1 <<= 1
+ f2 >>= 1
+ return z
+
+
+def _div_gf2(a, b):
+ """
+ Compute division of polynomials over GF(2).
+ Given a and b, it finds two polynomials q and r such that:
+
+ a = b*q + r with deg(r)<deg(b)
+ """
+
+ if (a < b):
+ return 0, a
+
+ deg = number.size
+ q = 0
+ r = a
+ d = deg(b)
+ while deg(r) >= d:
+ s = 1 << (deg(r) - d)
+ q ^= s
+ r ^= _mult_gf2(b, s)
+ return (q, r)
+
+
+class _Element(object):
+ """Element of GF(2^128) field"""
+
+ # The irreducible polynomial defining this field is 1+x+x^2+x^7+x^128
+ irr_poly = 1 + 2 + 4 + 128 + 2 ** 128
+
+ def __init__(self, encoded_value):
+ """Initialize the element to a certain value.
+
+ The value passed as parameter is internally encoded as
+ a 128-bit integer, where each bit represents a polynomial
+ coefficient. The LSB is the constant coefficient.
+ """
+
+ if is_native_int(encoded_value):
+ self._value = encoded_value
+ elif len(encoded_value) == 16:
+ self._value = bytes_to_long(encoded_value)
+ else:
+ raise ValueError("The encoded value must be an integer or a 16 byte string")
+
+ def __eq__(self, other):
+ return self._value == other._value
+
+ def __int__(self):
+ """Return the field element, encoded as a 128-bit integer."""
+ return self._value
+
+ def encode(self):
+ """Return the field element, encoded as a 16 byte string."""
+ return long_to_bytes(self._value, 16)
+
+ def __mul__(self, factor):
+
+ f1 = self._value
+ f2 = factor._value
+
+ # Make sure that f2 is the smallest, to speed up the loop
+ if f2 > f1:
+ f1, f2 = f2, f1
+
+ if self.irr_poly in (f1, f2):
+ return _Element(0)
+
+ mask1 = 2 ** 128
+ v, z = f1, 0
+ while f2:
+ # if f2 ^ 1: z ^= v
+ mask2 = int(bin(f2 & 1)[2:] * 128, base=2)
+ z = (mask2 & (z ^ v)) | ((mask1 - mask2 - 1) & z)
+ v <<= 1
+ # if v & mask1: v ^= self.irr_poly
+ mask3 = int(bin((v >> 128) & 1)[2:] * 128, base=2)
+ v = (mask3 & (v ^ self.irr_poly)) | ((mask1 - mask3 - 1) & v)
+ f2 >>= 1
+ return _Element(z)
+
+ def __add__(self, term):
+ return _Element(self._value ^ term._value)
+
+ def inverse(self):
+ """Return the inverse of this element in GF(2^128)."""
+
+ # We use the Extended GCD algorithm
+ # http://en.wikipedia.org/wiki/Polynomial_greatest_common_divisor
+
+ if self._value == 0:
+ raise ValueError("Inversion of zero")
+
+ r0, r1 = self._value, self.irr_poly
+ s0, s1 = 1, 0
+ while r1 > 0:
+ q = _div_gf2(r0, r1)[0]
+ r0, r1 = r1, r0 ^ _mult_gf2(q, r1)
+ s0, s1 = s1, s0 ^ _mult_gf2(q, s1)
+ return _Element(s0)
+
+ def __pow__(self, exponent):
+ result = _Element(self._value)
+ for _ in range(exponent - 1):
+ result = result * self
+ return result
+
+
+class Shamir(object):
+ """Shamir's secret sharing scheme.
+
+ A secret is split into ``n`` shares, and it is sufficient to collect
+ ``k`` of them to reconstruct the secret.
+ """
+
+ @staticmethod
+ def split(k, n, secret, ssss=False):
+ """Split a secret into ``n`` shares.
+
+ The secret can be reconstructed later using just ``k`` shares
+ out of the original ``n``.
+ Each share must be kept confidential to the person it was
+ assigned to.
+
+ Each share is associated to an index (starting from 1).
+
+ Args:
+ k (integer):
+ The sufficient number of shares to reconstruct the secret (``k < n``).
+ n (integer):
+ The number of shares that this method will create.
+ secret (byte string):
+ A byte string of 16 bytes (e.g. the AES 128 key).
+ ssss (bool):
+ If ``True``, the shares can be used with the ``ssss`` utility.
+ Default: ``False``.
+
+ Return (tuples):
+ ``n`` tuples. A tuple is meant for each participant and it contains two items:
+
+ 1. the unique index (an integer)
+ 2. the share (a byte string, 16 bytes)
+ """
+
+ #
+ # We create a polynomial with random coefficients in GF(2^128):
+ #
+ # p(x) = \sum_{i=0}^{k-1} c_i * x^i
+ #
+ # c_0 is the encoded secret
+ #
+
+ coeffs = [_Element(rng(16)) for i in range(k - 1)]
+ coeffs.append(_Element(secret))
+
+ # Each share is y_i = p(x_i) where x_i is the public index
+ # associated to each of the n users.
+
+ def make_share(user, coeffs, ssss):
+ idx = _Element(user)
+ share = _Element(0)
+ for coeff in coeffs:
+ share = idx * share + coeff
+ if ssss:
+ share += _Element(user) ** len(coeffs)
+ return share.encode()
+
+ return [(i, make_share(i, coeffs, ssss)) for i in range(1, n + 1)]
+
+ @staticmethod
+ def combine(shares, ssss=False):
+ """Recombine a secret, if enough shares are presented.
+
+ Args:
+ shares (tuples):
+ The *k* tuples, each containin the index (an integer) and
+ the share (a byte string, 16 bytes long) that were assigned to
+ a participant.
+ ssss (bool):
+ If ``True``, the shares were produced by the ``ssss`` utility.
+ Default: ``False``.
+
+ Return:
+ The original secret, as a byte string (16 bytes long).
+ """
+
+ #
+ # Given k points (x,y), the interpolation polynomial of degree k-1 is:
+ #
+ # L(x) = \sum_{j=0}^{k-1} y_i * l_j(x)
+ #
+ # where:
+ #
+ # l_j(x) = \prod_{ \overset{0 \le m \le k-1}{m \ne j} }
+ # \frac{x - x_m}{x_j - x_m}
+ #
+ # However, in this case we are purely interested in the constant
+ # coefficient of L(x).
+ #
+
+ k = len(shares)
+
+ gf_shares = []
+ for x in shares:
+ idx = _Element(x[0])
+ value = _Element(x[1])
+ if any(y[0] == idx for y in gf_shares):
+ raise ValueError("Duplicate share")
+ if ssss:
+ value += idx ** k
+ gf_shares.append((idx, value))
+
+ result = _Element(0)
+ for j in range(k):
+ x_j, y_j = gf_shares[j]
+
+ numerator = _Element(1)
+ denominator = _Element(1)
+
+ for m in range(k):
+ x_m = gf_shares[m][0]
+ if m != j:
+ numerator *= x_m
+ denominator *= x_j + x_m
+ result += y_j * numerator * denominator.inverse()
+ return result.encode()
diff --git a/frozen_deps/Cryptodome/Protocol/SecretSharing.pyi b/frozen_deps/Cryptodome/Protocol/SecretSharing.pyi
new file mode 100644
index 0000000..5952c99
--- /dev/null
+++ b/frozen_deps/Cryptodome/Protocol/SecretSharing.pyi
@@ -0,0 +1,22 @@
+from typing import Union, List, Tuple, Optional
+
+def _mult_gf2(f1: int, f2: int) -> int : ...
+def _div_gf2(a: int, b: int) -> int : ...
+
+class _Element(object):
+ irr_poly: int
+ def __init__(self, encoded_value: Union[int, bytes]) -> None: ...
+ def __eq__(self, other) -> bool: ...
+ def __int__(self) -> int: ...
+ def encode(self) -> bytes: ...
+ def __mul__(self, factor: int) -> _Element: ...
+ def __add__(self, term: _Element) -> _Element: ...
+ def inverse(self) -> _Element: ...
+ def __pow__(self, exponent) -> _Element: ...
+
+class Shamir(object):
+ @staticmethod
+ def split(k: int, n: int, secret: bytes, ssss: Optional[bool]) -> List[Tuple[int, bytes]]: ...
+ @staticmethod
+ def combine(shares: List[Tuple[int, bytes]], ssss: Optional[bool]) -> bytes: ...
+
diff --git a/frozen_deps/Cryptodome/Protocol/__init__.py b/frozen_deps/Cryptodome/Protocol/__init__.py
new file mode 100644
index 0000000..efdf034
--- /dev/null
+++ b/frozen_deps/Cryptodome/Protocol/__init__.py
@@ -0,0 +1,31 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+__all__ = ['KDF', 'SecretSharing']
diff --git a/frozen_deps/Cryptodome/Protocol/__init__.pyi b/frozen_deps/Cryptodome/Protocol/__init__.pyi
new file mode 100644
index 0000000..377ed90
--- /dev/null
+++ b/frozen_deps/Cryptodome/Protocol/__init__.pyi
@@ -0,0 +1 @@
+__all__ = ['KDF.pyi', 'SecretSharing.pyi']
diff --git a/frozen_deps/Cryptodome/Protocol/_scrypt.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Protocol/_scrypt.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..dbc8ca2
--- /dev/null
+++ b/frozen_deps/Cryptodome/Protocol/_scrypt.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/PublicKey/DSA.py b/frozen_deps/Cryptodome/PublicKey/DSA.py
new file mode 100644
index 0000000..2aaf864
--- /dev/null
+++ b/frozen_deps/Cryptodome/PublicKey/DSA.py
@@ -0,0 +1,679 @@
+# -*- coding: utf-8 -*-
+#
+# PublicKey/DSA.py : DSA signature primitive
+#
+# Written in 2008 by Dwayne C. Litzenberger <[email protected]>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+__all__ = ['generate', 'construct', 'DsaKey', 'import_key' ]
+
+import binascii
+import struct
+import itertools
+
+from Cryptodome.Util.py3compat import bchr, bord, tobytes, tostr, iter_range
+
+from Cryptodome import Random
+from Cryptodome.IO import PKCS8, PEM
+from Cryptodome.Hash import SHA256
+from Cryptodome.Util.asn1 import (
+ DerObject, DerSequence,
+ DerInteger, DerObjectId,
+ DerBitString,
+ )
+
+from Cryptodome.Math.Numbers import Integer
+from Cryptodome.Math.Primality import (test_probable_prime, COMPOSITE,
+ PROBABLY_PRIME)
+
+from Cryptodome.PublicKey import (_expand_subject_public_key_info,
+ _create_subject_public_key_info,
+ _extract_subject_public_key_info)
+
+# ; The following ASN.1 types are relevant for DSA
+#
+# SubjectPublicKeyInfo ::= SEQUENCE {
+# algorithm AlgorithmIdentifier,
+# subjectPublicKey BIT STRING
+# }
+#
+# id-dsa ID ::= { iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 1 }
+#
+# ; See RFC3279
+# Dss-Parms ::= SEQUENCE {
+# p INTEGER,
+# q INTEGER,
+# g INTEGER
+# }
+#
+# DSAPublicKey ::= INTEGER
+#
+# DSSPrivatKey_OpenSSL ::= SEQUENCE
+# version INTEGER,
+# p INTEGER,
+# q INTEGER,
+# g INTEGER,
+# y INTEGER,
+# x INTEGER
+# }
+#
+
+class DsaKey(object):
+ r"""Class defining an actual DSA key.
+ Do not instantiate directly.
+ Use :func:`generate`, :func:`construct` or :func:`import_key` instead.
+
+ :ivar p: DSA modulus
+ :vartype p: integer
+
+ :ivar q: Order of the subgroup
+ :vartype q: integer
+
+ :ivar g: Generator
+ :vartype g: integer
+
+ :ivar y: Public key
+ :vartype y: integer
+
+ :ivar x: Private key
+ :vartype x: integer
+ """
+
+ _keydata = ['y', 'g', 'p', 'q', 'x']
+
+ def __init__(self, key_dict):
+ input_set = set(key_dict.keys())
+ public_set = set(('y' , 'g', 'p', 'q'))
+ if not public_set.issubset(input_set):
+ raise ValueError("Some DSA components are missing = %s" %
+ str(public_set - input_set))
+ extra_set = input_set - public_set
+ if extra_set and extra_set != set(('x',)):
+ raise ValueError("Unknown DSA components = %s" %
+ str(extra_set - set(('x',))))
+ self._key = dict(key_dict)
+
+ def _sign(self, m, k):
+ if not self.has_private():
+ raise TypeError("DSA public key cannot be used for signing")
+ if not (1 < k < self.q):
+ raise ValueError("k is not between 2 and q-1")
+
+ x, q, p, g = [self._key[comp] for comp in ['x', 'q', 'p', 'g']]
+
+ blind_factor = Integer.random_range(min_inclusive=1,
+ max_exclusive=q)
+ inv_blind_k = (blind_factor * k).inverse(q)
+ blind_x = x * blind_factor
+
+ r = pow(g, k, p) % q # r = (g**k mod p) mod q
+ s = (inv_blind_k * (blind_factor * m + blind_x * r)) % q
+ return map(int, (r, s))
+
+ def _verify(self, m, sig):
+ r, s = sig
+ y, q, p, g = [self._key[comp] for comp in ['y', 'q', 'p', 'g']]
+ if not (0 < r < q) or not (0 < s < q):
+ return False
+ w = Integer(s).inverse(q)
+ u1 = (w * m) % q
+ u2 = (w * r) % q
+ v = (pow(g, u1, p) * pow(y, u2, p) % p) % q
+ return v == r
+
+ def has_private(self):
+ """Whether this is a DSA private key"""
+
+ return 'x' in self._key
+
+ def can_encrypt(self): # legacy
+ return False
+
+ def can_sign(self): # legacy
+ return True
+
+ def publickey(self):
+ """A matching DSA public key.
+
+ Returns:
+ a new :class:`DsaKey` object
+ """
+
+ public_components = dict((k, self._key[k]) for k in ('y', 'g', 'p', 'q'))
+ return DsaKey(public_components)
+
+ def __eq__(self, other):
+ if bool(self.has_private()) != bool(other.has_private()):
+ return False
+
+ result = True
+ for comp in self._keydata:
+ result = result and (getattr(self._key, comp, None) ==
+ getattr(other._key, comp, None))
+ return result
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def __getstate__(self):
+ # DSA key is not pickable
+ from pickle import PicklingError
+ raise PicklingError
+
+ def domain(self):
+ """The DSA domain parameters.
+
+ Returns
+ tuple : (p,q,g)
+ """
+
+ return [int(self._key[comp]) for comp in ('p', 'q', 'g')]
+
+ def __repr__(self):
+ attrs = []
+ for k in self._keydata:
+ if k == 'p':
+ bits = Integer(self.p).size_in_bits()
+ attrs.append("p(%d)" % (bits,))
+ elif hasattr(self, k):
+ attrs.append(k)
+ if self.has_private():
+ attrs.append("private")
+ # PY3K: This is meant to be text, do not change to bytes (data)
+ return "<%s @0x%x %s>" % (self.__class__.__name__, id(self), ",".join(attrs))
+
+ def __getattr__(self, item):
+ try:
+ return int(self._key[item])
+ except KeyError:
+ raise AttributeError(item)
+
+ def export_key(self, format='PEM', pkcs8=None, passphrase=None,
+ protection=None, randfunc=None):
+ """Export this DSA key.
+
+ Args:
+ format (string):
+ The encoding for the output:
+
+ - *'PEM'* (default). ASCII as per `RFC1421`_/ `RFC1423`_.
+ - *'DER'*. Binary ASN.1 encoding.
+ - *'OpenSSH'*. ASCII one-liner as per `RFC4253`_.
+ Only suitable for public keys, not for private keys.
+
+ passphrase (string):
+ *Private keys only*. The pass phrase to protect the output.
+
+ pkcs8 (boolean):
+ *Private keys only*. If ``True`` (default), the key is encoded
+ with `PKCS#8`_. If ``False``, it is encoded in the custom
+ OpenSSL/OpenSSH container.
+
+ protection (string):
+ *Only in combination with a pass phrase*.
+ The encryption scheme to use to protect the output.
+
+ If :data:`pkcs8` takes value ``True``, this is the PKCS#8
+ algorithm to use for deriving the secret and encrypting
+ the private DSA key.
+ For a complete list of algorithms, see :mod:`Cryptodome.IO.PKCS8`.
+ The default is *PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC*.
+
+ If :data:`pkcs8` is ``False``, the obsolete PEM encryption scheme is
+ used. It is based on MD5 for key derivation, and Triple DES for
+ encryption. Parameter :data:`protection` is then ignored.
+
+ The combination ``format='DER'`` and ``pkcs8=False`` is not allowed
+ if a passphrase is present.
+
+ randfunc (callable):
+ A function that returns random bytes.
+ By default it is :func:`Cryptodome.Random.get_random_bytes`.
+
+ Returns:
+ byte string : the encoded key
+
+ Raises:
+ ValueError : when the format is unknown or when you try to encrypt a private
+ key with *DER* format and OpenSSL/OpenSSH.
+
+ .. warning::
+ If you don't provide a pass phrase, the private key will be
+ exported in the clear!
+
+ .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
+ .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
+ .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt
+ .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
+ """
+
+ if passphrase is not None:
+ passphrase = tobytes(passphrase)
+
+ if randfunc is None:
+ randfunc = Random.get_random_bytes
+
+ if format == 'OpenSSH':
+ tup1 = [self._key[x].to_bytes() for x in ('p', 'q', 'g', 'y')]
+
+ def func(x):
+ if (bord(x[0]) & 0x80):
+ return bchr(0) + x
+ else:
+ return x
+
+ tup2 = [func(x) for x in tup1]
+ keyparts = [b'ssh-dss'] + tup2
+ keystring = b''.join(
+ [struct.pack(">I", len(kp)) + kp for kp in keyparts]
+ )
+ return b'ssh-dss ' + binascii.b2a_base64(keystring)[:-1]
+
+ # DER format is always used, even in case of PEM, which simply
+ # encodes it into BASE64.
+ params = DerSequence([self.p, self.q, self.g])
+ if self.has_private():
+ if pkcs8 is None:
+ pkcs8 = True
+ if pkcs8:
+ if not protection:
+ protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC'
+ private_key = DerInteger(self.x).encode()
+ binary_key = PKCS8.wrap(
+ private_key, oid, passphrase,
+ protection, key_params=params,
+ randfunc=randfunc
+ )
+ if passphrase:
+ key_type = 'ENCRYPTED PRIVATE'
+ else:
+ key_type = 'PRIVATE'
+ passphrase = None
+ else:
+ if format != 'PEM' and passphrase:
+ raise ValueError("DSA private key cannot be encrypted")
+ ints = [0, self.p, self.q, self.g, self.y, self.x]
+ binary_key = DerSequence(ints).encode()
+ key_type = "DSA PRIVATE"
+ else:
+ if pkcs8:
+ raise ValueError("PKCS#8 is only meaningful for private keys")
+
+ binary_key = _create_subject_public_key_info(oid,
+ DerInteger(self.y), params)
+ key_type = "PUBLIC"
+
+ if format == 'DER':
+ return binary_key
+ if format == 'PEM':
+ pem_str = PEM.encode(
+ binary_key, key_type + " KEY",
+ passphrase, randfunc
+ )
+ return tobytes(pem_str)
+ raise ValueError("Unknown key format '%s'. Cannot export the DSA key." % format)
+
+ # Backward-compatibility
+ exportKey = export_key
+
+ # Methods defined in PyCryptodome that we don't support anymore
+
+ def sign(self, M, K):
+ raise NotImplementedError("Use module Cryptodome.Signature.DSS instead")
+
+ def verify(self, M, signature):
+ raise NotImplementedError("Use module Cryptodome.Signature.DSS instead")
+
+ def encrypt(self, plaintext, K):
+ raise NotImplementedError
+
+ def decrypt(self, ciphertext):
+ raise NotImplementedError
+
+ def blind(self, M, B):
+ raise NotImplementedError
+
+ def unblind(self, M, B):
+ raise NotImplementedError
+
+ def size(self):
+ raise NotImplementedError
+
+
+def _generate_domain(L, randfunc):
+ """Generate a new set of DSA domain parameters"""
+
+ N = { 1024:160, 2048:224, 3072:256 }.get(L)
+ if N is None:
+ raise ValueError("Invalid modulus length (%d)" % L)
+
+ outlen = SHA256.digest_size * 8
+ n = (L + outlen - 1) // outlen - 1 # ceil(L/outlen) -1
+ b_ = L - 1 - (n * outlen)
+
+ # Generate q (A.1.1.2)
+ q = Integer(4)
+ upper_bit = 1 << (N - 1)
+ while test_probable_prime(q, randfunc) != PROBABLY_PRIME:
+ seed = randfunc(64)
+ U = Integer.from_bytes(SHA256.new(seed).digest()) & (upper_bit - 1)
+ q = U | upper_bit | 1
+
+ assert(q.size_in_bits() == N)
+
+ # Generate p (A.1.1.2)
+ offset = 1
+ upper_bit = 1 << (L - 1)
+ while True:
+ V = [ SHA256.new(seed + Integer(offset + j).to_bytes()).digest()
+ for j in iter_range(n + 1) ]
+ V = [ Integer.from_bytes(v) for v in V ]
+ W = sum([V[i] * (1 << (i * outlen)) for i in iter_range(n)],
+ (V[n] & ((1 << b_) - 1)) * (1 << (n * outlen)))
+
+ X = Integer(W + upper_bit) # 2^{L-1} < X < 2^{L}
+ assert(X.size_in_bits() == L)
+
+ c = X % (q * 2)
+ p = X - (c - 1) # 2q divides (p-1)
+ if p.size_in_bits() == L and \
+ test_probable_prime(p, randfunc) == PROBABLY_PRIME:
+ break
+ offset += n + 1
+
+ # Generate g (A.2.3, index=1)
+ e = (p - 1) // q
+ for count in itertools.count(1):
+ U = seed + b"ggen" + bchr(1) + Integer(count).to_bytes()
+ W = Integer.from_bytes(SHA256.new(U).digest())
+ g = pow(W, e, p)
+ if g != 1:
+ break
+
+ return (p, q, g, seed)
+
+
+def generate(bits, randfunc=None, domain=None):
+ """Generate a new DSA key pair.
+
+ The algorithm follows Appendix A.1/A.2 and B.1 of `FIPS 186-4`_,
+ respectively for domain generation and key pair generation.
+
+ Args:
+ bits (integer):
+ Key length, or size (in bits) of the DSA modulus *p*.
+ It must be 1024, 2048 or 3072.
+
+ randfunc (callable):
+ Random number generation function; it accepts a single integer N
+ and return a string of random data N bytes long.
+ If not specified, :func:`Cryptodome.Random.get_random_bytes` is used.
+
+ domain (tuple):
+ The DSA domain parameters *p*, *q* and *g* as a list of 3
+ integers. Size of *p* and *q* must comply to `FIPS 186-4`_.
+ If not specified, the parameters are created anew.
+
+ Returns:
+ :class:`DsaKey` : a new DSA key object
+
+ Raises:
+ ValueError : when **bits** is too little, too big, or not a multiple of 64.
+
+ .. _FIPS 186-4: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
+ """
+
+ if randfunc is None:
+ randfunc = Random.get_random_bytes
+
+ if domain:
+ p, q, g = map(Integer, domain)
+
+ ## Perform consistency check on domain parameters
+ # P and Q must be prime
+ fmt_error = test_probable_prime(p) == COMPOSITE
+ fmt_error = test_probable_prime(q) == COMPOSITE
+ # Verify Lagrange's theorem for sub-group
+ fmt_error |= ((p - 1) % q) != 0
+ fmt_error |= g <= 1 or g >= p
+ fmt_error |= pow(g, q, p) != 1
+ if fmt_error:
+ raise ValueError("Invalid DSA domain parameters")
+ else:
+ p, q, g, _ = _generate_domain(bits, randfunc)
+
+ L = p.size_in_bits()
+ N = q.size_in_bits()
+
+ if L != bits:
+ raise ValueError("Mismatch between size of modulus (%d)"
+ " and 'bits' parameter (%d)" % (L, bits))
+
+ if (L, N) not in [(1024, 160), (2048, 224),
+ (2048, 256), (3072, 256)]:
+ raise ValueError("Lengths of p and q (%d, %d) are not compatible"
+ "to FIPS 186-3" % (L, N))
+
+ if not 1 < g < p:
+ raise ValueError("Incorrent DSA generator")
+
+ # B.1.1
+ c = Integer.random(exact_bits=N + 64, randfunc=randfunc)
+ x = c % (q - 1) + 1 # 1 <= x <= q-1
+ y = pow(g, x, p)
+
+ key_dict = { 'y':y, 'g':g, 'p':p, 'q':q, 'x':x }
+ return DsaKey(key_dict)
+
+
+def construct(tup, consistency_check=True):
+ """Construct a DSA key from a tuple of valid DSA components.
+
+ Args:
+ tup (tuple):
+ A tuple of long integers, with 4 or 5 items
+ in the following order:
+
+ 1. Public key (*y*).
+ 2. Sub-group generator (*g*).
+ 3. Modulus, finite field order (*p*).
+ 4. Sub-group order (*q*).
+ 5. Private key (*x*). Optional.
+
+ consistency_check (boolean):
+ If ``True``, the library will verify that the provided components
+ fulfil the main DSA properties.
+
+ Raises:
+ ValueError: when the key being imported fails the most basic DSA validity checks.
+
+ Returns:
+ :class:`DsaKey` : a DSA key object
+ """
+
+ key_dict = dict(zip(('y', 'g', 'p', 'q', 'x'), map(Integer, tup)))
+ key = DsaKey(key_dict)
+
+ fmt_error = False
+ if consistency_check:
+ # P and Q must be prime
+ fmt_error = test_probable_prime(key.p) == COMPOSITE
+ fmt_error = test_probable_prime(key.q) == COMPOSITE
+ # Verify Lagrange's theorem for sub-group
+ fmt_error |= ((key.p - 1) % key.q) != 0
+ fmt_error |= key.g <= 1 or key.g >= key.p
+ fmt_error |= pow(key.g, key.q, key.p) != 1
+ # Public key
+ fmt_error |= key.y <= 0 or key.y >= key.p
+ if hasattr(key, 'x'):
+ fmt_error |= key.x <= 0 or key.x >= key.q
+ fmt_error |= pow(key.g, key.x, key.p) != key.y
+
+ if fmt_error:
+ raise ValueError("Invalid DSA key components")
+
+ return key
+
+
+# Dss-Parms ::= SEQUENCE {
+# p OCTET STRING,
+# q OCTET STRING,
+# g OCTET STRING
+# }
+# DSAPublicKey ::= INTEGER -- public key, y
+
+def _import_openssl_private(encoded, passphrase, params):
+ if params:
+ raise ValueError("DSA private key already comes with parameters")
+ der = DerSequence().decode(encoded, nr_elements=6, only_ints_expected=True)
+ if der[0] != 0:
+ raise ValueError("No version found")
+ tup = [der[comp] for comp in (4, 3, 1, 2, 5)]
+ return construct(tup)
+
+
+def _import_subjectPublicKeyInfo(encoded, passphrase, params):
+
+ algoid, encoded_key, emb_params = _expand_subject_public_key_info(encoded)
+ if algoid != oid:
+ raise ValueError("No DSA subjectPublicKeyInfo")
+ if params and emb_params:
+ raise ValueError("Too many DSA parameters")
+
+ y = DerInteger().decode(encoded_key).value
+ p, q, g = list(DerSequence().decode(params or emb_params))
+ tup = (y, g, p, q)
+ return construct(tup)
+
+
+def _import_x509_cert(encoded, passphrase, params):
+
+ sp_info = _extract_subject_public_key_info(encoded)
+ return _import_subjectPublicKeyInfo(sp_info, None, params)
+
+
+def _import_pkcs8(encoded, passphrase, params):
+ if params:
+ raise ValueError("PKCS#8 already includes parameters")
+ k = PKCS8.unwrap(encoded, passphrase)
+ if k[0] != oid:
+ raise ValueError("No PKCS#8 encoded DSA key")
+ x = DerInteger().decode(k[1]).value
+ p, q, g = list(DerSequence().decode(k[2]))
+ tup = (pow(g, x, p), g, p, q, x)
+ return construct(tup)
+
+
+def _import_key_der(key_data, passphrase, params):
+ """Import a DSA key (public or private half), encoded in DER form."""
+
+ decodings = (_import_openssl_private,
+ _import_subjectPublicKeyInfo,
+ _import_x509_cert,
+ _import_pkcs8)
+
+ for decoding in decodings:
+ try:
+ return decoding(key_data, passphrase, params)
+ except ValueError:
+ pass
+
+ raise ValueError("DSA key format is not supported")
+
+
+def import_key(extern_key, passphrase=None):
+ """Import a DSA key.
+
+ Args:
+ extern_key (string or byte string):
+ The DSA key to import.
+
+ The following formats are supported for a DSA **public** key:
+
+ - X.509 certificate (binary DER or PEM)
+ - X.509 ``subjectPublicKeyInfo`` (binary DER or PEM)
+ - OpenSSH (ASCII one-liner, see `RFC4253`_)
+
+ The following formats are supported for a DSA **private** key:
+
+ - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo``
+ DER SEQUENCE (binary or PEM)
+ - OpenSSL/OpenSSH custom format (binary or PEM)
+
+ For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.
+
+ passphrase (string):
+ In case of an encrypted private key, this is the pass phrase
+ from which the decryption key is derived.
+
+ Encryption may be applied either at the `PKCS#8`_ or at the PEM level.
+
+ Returns:
+ :class:`DsaKey` : a DSA key object
+
+ Raises:
+ ValueError : when the given key cannot be parsed (possibly because
+ the pass phrase is wrong).
+
+ .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
+ .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
+ .. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt
+ .. _PKCS#8: http://www.ietf.org/rfc/rfc5208.txt
+ """
+
+ extern_key = tobytes(extern_key)
+ if passphrase is not None:
+ passphrase = tobytes(passphrase)
+
+ if extern_key.startswith(b'-----'):
+ # This is probably a PEM encoded key
+ (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
+ if enc_flag:
+ passphrase = None
+ return _import_key_der(der, passphrase, None)
+
+ if extern_key.startswith(b'ssh-dss '):
+ # This is probably a public OpenSSH key
+ keystring = binascii.a2b_base64(extern_key.split(b' ')[1])
+ keyparts = []
+ while len(keystring) > 4:
+ length = struct.unpack(">I", keystring[:4])[0]
+ keyparts.append(keystring[4:4 + length])
+ keystring = keystring[4 + length:]
+ if keyparts[0] == b"ssh-dss":
+ tup = [Integer.from_bytes(keyparts[x]) for x in (4, 3, 1, 2)]
+ return construct(tup)
+
+ if len(extern_key) > 0 and bord(extern_key[0]) == 0x30:
+ # This is probably a DER encoded key
+ return _import_key_der(extern_key, passphrase, None)
+
+ raise ValueError("DSA key format is not supported")
+
+
+# Backward compatibility
+importKey = import_key
+
+#: `Object ID`_ for a DSA key.
+#:
+#: id-dsa ID ::= { iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 1 }
+#:
+#: .. _`Object ID`: http://www.alvestrand.no/objectid/1.2.840.10040.4.1.html
+oid = "1.2.840.10040.4.1"
diff --git a/frozen_deps/Cryptodome/PublicKey/DSA.pyi b/frozen_deps/Cryptodome/PublicKey/DSA.pyi
new file mode 100644
index 0000000..9977a0f
--- /dev/null
+++ b/frozen_deps/Cryptodome/PublicKey/DSA.pyi
@@ -0,0 +1,30 @@
+from typing import Dict, Tuple, Callable, Union, Optional
+
+__all__ = ['generate', 'construct', 'DsaKey', 'import_key' ]
+
+RNG = Callable[[int], bytes]
+
+class DsaKey(object):
+ def __init__(self, key_dict: Dict[str, int]) -> None: ...
+ def has_private(self) -> bool: ...
+ def can_encrypt(self) -> bool: ... # legacy
+ def can_sign(self) -> bool: ... # legacy
+ def publickey(self) -> DsaKey: ...
+ def __eq__(self, other: object) -> bool: ...
+ def __ne__(self, other: object) -> bool: ...
+ def __getstate__(self) -> None: ...
+ def domain(self) -> Tuple[int, int, int]: ...
+ def __repr__(self) -> str: ...
+ def __getattr__(self, item: str) -> int: ...
+ def export_key(self, format: Optional[str]="PEM", pkcs8: Optional[bool]=None, passphrase: Optional[str]=None,
+ protection: Optional[str]=None, randfunc: Optional[RNG]=None) -> bytes: ...
+ # Backward-compatibility
+ exportKey = export_key
+
+def generate(bits: int, randfunc: Optional[RNG]=None, domain: Optional[Tuple[int, int, int]]=None) -> DsaKey: ...
+def construct(tup: Union[Tuple[int, int, int, int], Tuple[int, int, int, int, int]], consistency_check: Optional[bool]=True) -> DsaKey: ...
+def import_key(extern_key: Union[str, bytes], passphrase: Optional[str]=None) -> DsaKey: ...
+# Backward compatibility
+importKey = import_key
+
+oid: str
diff --git a/frozen_deps/Cryptodome/PublicKey/ECC.py b/frozen_deps/Cryptodome/PublicKey/ECC.py
new file mode 100644
index 0000000..e83664b
--- /dev/null
+++ b/frozen_deps/Cryptodome/PublicKey/ECC.py
@@ -0,0 +1,1184 @@
+# ===================================================================
+#
+# Copyright (c) 2015, Legrandin <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+from __future__ import print_function
+
+import re
+import sys
+import struct
+import binascii
+from collections import namedtuple
+
+from Cryptodome.Util.py3compat import bord, tobytes, tostr, bchr, is_string
+from Cryptodome.Util.number import bytes_to_long, long_to_bytes
+
+from Cryptodome.Math.Numbers import Integer
+from Cryptodome.Util.asn1 import (DerObjectId, DerOctetString, DerSequence,
+ DerBitString)
+
+from Cryptodome.PublicKey import (_expand_subject_public_key_info,
+ _create_subject_public_key_info,
+ _extract_subject_public_key_info)
+
+from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer,
+ SmartPointer, c_size_t, c_uint8_ptr,
+ c_ulonglong)
+
+from Cryptodome.Random import get_random_bytes
+from Cryptodome.Random.random import getrandbits
+
+
+_ec_lib = load_pycryptodome_raw_lib("Cryptodome.PublicKey._ec_ws", """
+typedef void EcContext;
+typedef void EcPoint;
+int ec_ws_new_context(EcContext **pec_ctx,
+ const uint8_t *modulus,
+ const uint8_t *b,
+ const uint8_t *order,
+ size_t len,
+ uint64_t seed);
+void ec_free_context(EcContext *ec_ctx);
+int ec_ws_new_point(EcPoint **pecp,
+ const uint8_t *x,
+ const uint8_t *y,
+ size_t len,
+ const EcContext *ec_ctx);
+void ec_free_point(EcPoint *ecp);
+int ec_ws_get_xy(uint8_t *x,
+ uint8_t *y,
+ size_t len,
+ const EcPoint *ecp);
+int ec_ws_double(EcPoint *p);
+int ec_ws_add(EcPoint *ecpa, EcPoint *ecpb);
+int ec_ws_scalar(EcPoint *ecp,
+ const uint8_t *k,
+ size_t len,
+ uint64_t seed);
+int ec_ws_clone(EcPoint **pecp2, const EcPoint *ecp);
+int ec_ws_copy(EcPoint *ecp1, const EcPoint *ecp2);
+int ec_ws_cmp(const EcPoint *ecp1, const EcPoint *ecp2);
+int ec_ws_neg(EcPoint *p);
+int ec_ws_normalize(EcPoint *ecp);
+int ec_ws_is_pai(EcPoint *ecp);
+""")
+
+_Curve = namedtuple("_Curve", "p b order Gx Gy G modulus_bits oid context desc openssh")
+_curves = {}
+
+
+p256_names = ["p256", "NIST P-256", "P-256", "prime256v1", "secp256r1",
+ "nistp256"]
+
+
+def init_p256():
+ p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff
+ b = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b
+ order = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551
+ Gx = 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296
+ Gy = 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5
+
+ p256_modulus = long_to_bytes(p, 32)
+ p256_b = long_to_bytes(b, 32)
+ p256_order = long_to_bytes(order, 32)
+
+ ec_p256_context = VoidPointer()
+ result = _ec_lib.ec_ws_new_context(ec_p256_context.address_of(),
+ c_uint8_ptr(p256_modulus),
+ c_uint8_ptr(p256_b),
+ c_uint8_ptr(p256_order),
+ c_size_t(len(p256_modulus)),
+ c_ulonglong(getrandbits(64))
+ )
+ if result:
+ raise ImportError("Error %d initializing P-256 context" % result)
+
+ context = SmartPointer(ec_p256_context.get(), _ec_lib.ec_free_context)
+ p256 = _Curve(Integer(p),
+ Integer(b),
+ Integer(order),
+ Integer(Gx),
+ Integer(Gy),
+ None,
+ 256,
+ "1.2.840.10045.3.1.7", # ANSI X9.62
+ context,
+ "NIST P-256",
+ "ecdsa-sha2-nistp256")
+ global p256_names
+ _curves.update(dict.fromkeys(p256_names, p256))
+
+
+init_p256()
+del init_p256
+
+
+p384_names = ["p384", "NIST P-384", "P-384", "prime384v1", "secp384r1",
+ "nistp384"]
+
+
+def init_p384():
+ p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff
+ b = 0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef
+ order = 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973
+ Gx = 0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760aB7
+ Gy = 0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5F
+
+ p384_modulus = long_to_bytes(p, 48)
+ p384_b = long_to_bytes(b, 48)
+ p384_order = long_to_bytes(order, 48)
+
+ ec_p384_context = VoidPointer()
+ result = _ec_lib.ec_ws_new_context(ec_p384_context.address_of(),
+ c_uint8_ptr(p384_modulus),
+ c_uint8_ptr(p384_b),
+ c_uint8_ptr(p384_order),
+ c_size_t(len(p384_modulus)),
+ c_ulonglong(getrandbits(64))
+ )
+ if result:
+ raise ImportError("Error %d initializing P-384 context" % result)
+
+ context = SmartPointer(ec_p384_context.get(), _ec_lib.ec_free_context)
+ p384 = _Curve(Integer(p),
+ Integer(b),
+ Integer(order),
+ Integer(Gx),
+ Integer(Gy),
+ None,
+ 384,
+ "1.3.132.0.34", # SEC 2
+ context,
+ "NIST P-384",
+ "ecdsa-sha2-nistp384")
+ global p384_names
+ _curves.update(dict.fromkeys(p384_names, p384))
+
+
+init_p384()
+del init_p384
+
+
+p521_names = ["p521", "NIST P-521", "P-521", "prime521v1", "secp521r1",
+ "nistp521"]
+
+
+def init_p521():
+ p = 0x000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ b = 0x00000051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00
+ order = 0x000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409
+ Gx = 0x000000c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66
+ Gy = 0x0000011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650
+
+ p521_modulus = long_to_bytes(p, 66)
+ p521_b = long_to_bytes(b, 66)
+ p521_order = long_to_bytes(order, 66)
+
+ ec_p521_context = VoidPointer()
+ result = _ec_lib.ec_ws_new_context(ec_p521_context.address_of(),
+ c_uint8_ptr(p521_modulus),
+ c_uint8_ptr(p521_b),
+ c_uint8_ptr(p521_order),
+ c_size_t(len(p521_modulus)),
+ c_ulonglong(getrandbits(64))
+ )
+ if result:
+ raise ImportError("Error %d initializing P-521 context" % result)
+
+ context = SmartPointer(ec_p521_context.get(), _ec_lib.ec_free_context)
+ p521 = _Curve(Integer(p),
+ Integer(b),
+ Integer(order),
+ Integer(Gx),
+ Integer(Gy),
+ None,
+ 521,
+ "1.3.132.0.35", # SEC 2
+ context,
+ "NIST P-521",
+ "ecdsa-sha2-nistp521")
+ global p521_names
+ _curves.update(dict.fromkeys(p521_names, p521))
+
+
+init_p521()
+del init_p521
+
+
+class UnsupportedEccFeature(ValueError):
+ pass
+
+
+class EccPoint(object):
+ """A class to abstract a point over an Elliptic Curve.
+
+ The class support special methods for:
+
+ * Adding two points: ``R = S + T``
+ * In-place addition: ``S += T``
+ * Negating a point: ``R = -T``
+ * Comparing two points: ``if S == T: ...``
+ * Multiplying a point by a scalar: ``R = S*k``
+ * In-place multiplication by a scalar: ``T *= k``
+
+ :ivar x: The affine X-coordinate of the ECC point
+ :vartype x: integer
+
+ :ivar y: The affine Y-coordinate of the ECC point
+ :vartype y: integer
+
+ :ivar xy: The tuple with X- and Y- coordinates
+ """
+
+ def __init__(self, x, y, curve="p256"):
+
+ try:
+ self._curve = _curves[curve]
+ except KeyError:
+ raise ValueError("Unknown curve name %s" % str(curve))
+ self._curve_name = curve
+
+ modulus_bytes = self.size_in_bytes()
+ context = self._curve.context
+
+ xb = long_to_bytes(x, modulus_bytes)
+ yb = long_to_bytes(y, modulus_bytes)
+ if len(xb) != modulus_bytes or len(yb) != modulus_bytes:
+ raise ValueError("Incorrect coordinate length")
+
+ self._point = VoidPointer()
+ result = _ec_lib.ec_ws_new_point(self._point.address_of(),
+ c_uint8_ptr(xb),
+ c_uint8_ptr(yb),
+ c_size_t(modulus_bytes),
+ context.get())
+ if result:
+ if result == 15:
+ raise ValueError("The EC point does not belong to the curve")
+ raise ValueError("Error %d while instantiating an EC point" % result)
+
+ # Ensure that object disposal of this Python object will (eventually)
+ # free the memory allocated by the raw library for the EC point
+ self._point = SmartPointer(self._point.get(),
+ _ec_lib.ec_free_point)
+
+ def set(self, point):
+ self._point = VoidPointer()
+ result = _ec_lib.ec_ws_clone(self._point.address_of(),
+ point._point.get())
+ if result:
+ raise ValueError("Error %d while cloning an EC point" % result)
+
+ self._point = SmartPointer(self._point.get(),
+ _ec_lib.ec_free_point)
+ return self
+
+ def __eq__(self, point):
+ return 0 == _ec_lib.ec_ws_cmp(self._point.get(), point._point.get())
+
+ def __neg__(self):
+ np = self.copy()
+ result = _ec_lib.ec_ws_neg(np._point.get())
+ if result:
+ raise ValueError("Error %d while inverting an EC point" % result)
+ return np
+
+ def copy(self):
+ """Return a copy of this point."""
+ x, y = self.xy
+ np = EccPoint(x, y, self._curve_name)
+ return np
+
+ def is_point_at_infinity(self):
+ """``True`` if this is the point-at-infinity."""
+ return self.xy == (0, 0)
+
+ def point_at_infinity(self):
+ """Return the point-at-infinity for the curve this point is on."""
+ return EccPoint(0, 0, self._curve_name)
+
+ @property
+ def x(self):
+ return self.xy[0]
+
+ @property
+ def y(self):
+ return self.xy[1]
+
+ @property
+ def xy(self):
+ modulus_bytes = self.size_in_bytes()
+ xb = bytearray(modulus_bytes)
+ yb = bytearray(modulus_bytes)
+ result = _ec_lib.ec_ws_get_xy(c_uint8_ptr(xb),
+ c_uint8_ptr(yb),
+ c_size_t(modulus_bytes),
+ self._point.get())
+ if result:
+ raise ValueError("Error %d while encoding an EC point" % result)
+
+ return (Integer(bytes_to_long(xb)), Integer(bytes_to_long(yb)))
+
+ def size_in_bytes(self):
+ """Size of each coordinate, in bytes."""
+ return (self.size_in_bits() + 7) // 8
+
+ def size_in_bits(self):
+ """Size of each coordinate, in bits."""
+ return self._curve.modulus_bits
+
+ def double(self):
+ """Double this point (in-place operation).
+
+ :Return:
+ :class:`EccPoint` : this same object (to enable chaining)
+ """
+
+ result = _ec_lib.ec_ws_double(self._point.get())
+ if result:
+ raise ValueError("Error %d while doubling an EC point" % result)
+ return self
+
+ def __iadd__(self, point):
+ """Add a second point to this one"""
+
+ result = _ec_lib.ec_ws_add(self._point.get(), point._point.get())
+ if result:
+ if result == 16:
+ raise ValueError("EC points are not on the same curve")
+ raise ValueError("Error %d while adding two EC points" % result)
+ return self
+
+ def __add__(self, point):
+ """Return a new point, the addition of this one and another"""
+
+ np = self.copy()
+ np += point
+ return np
+
+ def __imul__(self, scalar):
+ """Multiply this point by a scalar"""
+
+ if scalar < 0:
+ raise ValueError("Scalar multiplication is only defined for non-negative integers")
+ sb = long_to_bytes(scalar)
+ result = _ec_lib.ec_ws_scalar(self._point.get(),
+ c_uint8_ptr(sb),
+ c_size_t(len(sb)),
+ c_ulonglong(getrandbits(64)))
+ if result:
+ raise ValueError("Error %d during scalar multiplication" % result)
+ return self
+
+ def __mul__(self, scalar):
+ """Return a new point, the scalar product of this one"""
+
+ np = self.copy()
+ np *= scalar
+ return np
+
+ def __rmul__(self, left_hand):
+ return self.__mul__(left_hand)
+
+
+# Last piece of initialization
+p256_G = EccPoint(_curves['p256'].Gx, _curves['p256'].Gy, "p256")
+p256 = _curves['p256']._replace(G=p256_G)
+_curves.update(dict.fromkeys(p256_names, p256))
+del p256_G, p256, p256_names
+
+p384_G = EccPoint(_curves['p384'].Gx, _curves['p384'].Gy, "p384")
+p384 = _curves['p384']._replace(G=p384_G)
+_curves.update(dict.fromkeys(p384_names, p384))
+del p384_G, p384, p384_names
+
+p521_G = EccPoint(_curves['p521'].Gx, _curves['p521'].Gy, "p521")
+p521 = _curves['p521']._replace(G=p521_G)
+_curves.update(dict.fromkeys(p521_names, p521))
+del p521_G, p521, p521_names
+
+
+class EccKey(object):
+ r"""Class defining an ECC key.
+ Do not instantiate directly.
+ Use :func:`generate`, :func:`construct` or :func:`import_key` instead.
+
+ :ivar curve: The name of the ECC as defined in :numref:`curve_names`.
+ :vartype curve: string
+
+ :ivar pointQ: an ECC point representating the public component
+ :vartype pointQ: :class:`EccPoint`
+
+ :ivar d: A scalar representating the private component
+ :vartype d: integer
+ """
+
+ def __init__(self, **kwargs):
+ """Create a new ECC key
+
+ Keywords:
+ curve : string
+ It must be *"p256"*, *"P-256"*, *"prime256v1"* or *"secp256r1"*.
+ d : integer
+ Only for a private key. It must be in the range ``[1..order-1]``.
+ point : EccPoint
+ Mandatory for a public key. If provided for a private key,
+ the implementation will NOT check whether it matches ``d``.
+ """
+
+ kwargs_ = dict(kwargs)
+ curve_name = kwargs_.pop("curve", None)
+ self._d = kwargs_.pop("d", None)
+ self._point = kwargs_.pop("point", None)
+ if kwargs_:
+ raise TypeError("Unknown parameters: " + str(kwargs_))
+
+ if curve_name not in _curves:
+ raise ValueError("Unsupported curve (%s)", curve_name)
+ self._curve = _curves[curve_name]
+
+ if self._d is None:
+ if self._point is None:
+ raise ValueError("Either private or public ECC component must be specified, not both")
+ else:
+ self._d = Integer(self._d)
+ if not 1 <= self._d < self._curve.order:
+ raise ValueError("Invalid ECC private component")
+
+ self.curve = self._curve.desc
+
+ def __eq__(self, other):
+ if other.has_private() != self.has_private():
+ return False
+
+ return other.pointQ == self.pointQ
+
+ def __repr__(self):
+ if self.has_private():
+ extra = ", d=%d" % int(self._d)
+ else:
+ extra = ""
+ x, y = self.pointQ.xy
+ return "EccKey(curve='%s', point_x=%d, point_y=%d%s)" % (self._curve.desc, x, y, extra)
+
+ def has_private(self):
+ """``True`` if this key can be used for making signatures or decrypting data."""
+
+ return self._d is not None
+
+ def _sign(self, z, k):
+ assert 0 < k < self._curve.order
+
+ order = self._curve.order
+ blind = Integer.random_range(min_inclusive=1,
+ max_exclusive=order)
+
+ blind_d = self._d * blind
+ inv_blind_k = (blind * k).inverse(order)
+
+ r = (self._curve.G * k).x % order
+ s = inv_blind_k * (blind * z + blind_d * r) % order
+ return (r, s)
+
+ def _verify(self, z, rs):
+ order = self._curve.order
+ sinv = rs[1].inverse(order)
+ point1 = self._curve.G * ((sinv * z) % order)
+ point2 = self.pointQ * ((sinv * rs[0]) % order)
+ return (point1 + point2).x == rs[0]
+
+ @property
+ def d(self):
+ if not self.has_private():
+ raise ValueError("This is not a private ECC key")
+ return self._d
+
+ @property
+ def pointQ(self):
+ if self._point is None:
+ self._point = self._curve.G * self._d
+ return self._point
+
+ def public_key(self):
+ """A matching ECC public key.
+
+ Returns:
+ a new :class:`EccKey` object
+ """
+
+ return EccKey(curve=self._curve.desc, point=self.pointQ)
+
+ def _export_subjectPublicKeyInfo(self, compress):
+
+ # See 2.2 in RFC5480 and 2.3.3 in SEC1
+ # The first byte is:
+ # - 0x02: compressed, only X-coordinate, Y-coordinate is even
+ # - 0x03: compressed, only X-coordinate, Y-coordinate is odd
+ # - 0x04: uncompressed, X-coordinate is followed by Y-coordinate
+ #
+ # PAI is in theory encoded as 0x00.
+
+ modulus_bytes = self.pointQ.size_in_bytes()
+
+ if compress:
+ first_byte = 2 + self.pointQ.y.is_odd()
+ public_key = (bchr(first_byte) +
+ self.pointQ.x.to_bytes(modulus_bytes))
+ else:
+ public_key = (b'\x04' +
+ self.pointQ.x.to_bytes(modulus_bytes) +
+ self.pointQ.y.to_bytes(modulus_bytes))
+
+ unrestricted_oid = "1.2.840.10045.2.1"
+ return _create_subject_public_key_info(unrestricted_oid,
+ public_key,
+ DerObjectId(self._curve.oid))
+
+ def _export_private_der(self, include_ec_params=True):
+
+ assert self.has_private()
+
+ # ECPrivateKey ::= SEQUENCE {
+ # version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
+ # privateKey OCTET STRING,
+ # parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
+ # publicKey [1] BIT STRING OPTIONAL
+ # }
+
+ # Public key - uncompressed form
+ modulus_bytes = self.pointQ.size_in_bytes()
+ public_key = (b'\x04' +
+ self.pointQ.x.to_bytes(modulus_bytes) +
+ self.pointQ.y.to_bytes(modulus_bytes))
+
+ seq = [1,
+ DerOctetString(self.d.to_bytes(modulus_bytes)),
+ DerObjectId(self._curve.oid, explicit=0),
+ DerBitString(public_key, explicit=1)]
+
+ if not include_ec_params:
+ del seq[2]
+
+ return DerSequence(seq).encode()
+
+ def _export_pkcs8(self, **kwargs):
+ from Cryptodome.IO import PKCS8
+
+ if kwargs.get('passphrase', None) is not None and 'protection' not in kwargs:
+ raise ValueError("At least the 'protection' parameter should be present")
+
+ unrestricted_oid = "1.2.840.10045.2.1"
+ private_key = self._export_private_der(include_ec_params=False)
+ result = PKCS8.wrap(private_key,
+ unrestricted_oid,
+ key_params=DerObjectId(self._curve.oid),
+ **kwargs)
+ return result
+
+ def _export_public_pem(self, compress):
+ from Cryptodome.IO import PEM
+
+ encoded_der = self._export_subjectPublicKeyInfo(compress)
+ return PEM.encode(encoded_der, "PUBLIC KEY")
+
+ def _export_private_pem(self, passphrase, **kwargs):
+ from Cryptodome.IO import PEM
+
+ encoded_der = self._export_private_der()
+ return PEM.encode(encoded_der, "EC PRIVATE KEY", passphrase, **kwargs)
+
+ def _export_private_clear_pkcs8_in_clear_pem(self):
+ from Cryptodome.IO import PEM
+
+ encoded_der = self._export_pkcs8()
+ return PEM.encode(encoded_der, "PRIVATE KEY")
+
+ def _export_private_encrypted_pkcs8_in_clear_pem(self, passphrase, **kwargs):
+ from Cryptodome.IO import PEM
+
+ assert passphrase
+ if 'protection' not in kwargs:
+ raise ValueError("At least the 'protection' parameter should be present")
+ encoded_der = self._export_pkcs8(passphrase=passphrase, **kwargs)
+ return PEM.encode(encoded_der, "ENCRYPTED PRIVATE KEY")
+
+ def _export_openssh(self, compress):
+ if self.has_private():
+ raise ValueError("Cannot export OpenSSH private keys")
+
+ desc = self._curve.openssh
+ modulus_bytes = self.pointQ.size_in_bytes()
+
+ if compress:
+ first_byte = 2 + self.pointQ.y.is_odd()
+ public_key = (bchr(first_byte) +
+ self.pointQ.x.to_bytes(modulus_bytes))
+ else:
+ public_key = (b'\x04' +
+ self.pointQ.x.to_bytes(modulus_bytes) +
+ self.pointQ.y.to_bytes(modulus_bytes))
+
+ middle = desc.split("-")[2]
+ comps = (tobytes(desc), tobytes(middle), public_key)
+ blob = b"".join([struct.pack(">I", len(x)) + x for x in comps])
+ return desc + " " + tostr(binascii.b2a_base64(blob))
+
+ def export_key(self, **kwargs):
+ """Export this ECC key.
+
+ Args:
+ format (string):
+ The format to use for encoding the key:
+
+ - ``'DER'``. The key will be encoded in ASN.1 DER format (binary).
+ For a public key, the ASN.1 ``subjectPublicKeyInfo`` structure
+ defined in `RFC5480`_ will be used.
+ For a private key, the ASN.1 ``ECPrivateKey`` structure defined
+ in `RFC5915`_ is used instead (possibly within a PKCS#8 envelope,
+ see the ``use_pkcs8`` flag below).
+ - ``'PEM'``. The key will be encoded in a PEM_ envelope (ASCII).
+ - ``'OpenSSH'``. The key will be encoded in the OpenSSH_ format
+ (ASCII, public keys only).
+
+ passphrase (byte string or string):
+ The passphrase to use for protecting the private key.
+
+ use_pkcs8 (boolean):
+ Only relevant for private keys.
+
+ If ``True`` (default and recommended), the `PKCS#8`_ representation
+ will be used.
+
+ If ``False``, the much weaker `PEM encryption`_ mechanism will be used.
+
+ protection (string):
+ When a private key is exported with password-protection
+ and PKCS#8 (both ``DER`` and ``PEM`` formats), this parameter MUST be
+ present and be a valid algorithm supported by :mod:`Cryptodome.IO.PKCS8`.
+ It is recommended to use ``PBKDF2WithHMAC-SHA1AndAES128-CBC``.
+
+ compress (boolean):
+ If ``True``, a more compact representation of the public key
+ with the X-coordinate only is used.
+
+ If ``False`` (default), the full public key will be exported.
+
+ .. warning::
+ If you don't provide a passphrase, the private key will be
+ exported in the clear!
+
+ .. note::
+ When exporting a private key with password-protection and `PKCS#8`_
+ (both ``DER`` and ``PEM`` formats), any extra parameters
+ to ``export_key()`` will be passed to :mod:`Cryptodome.IO.PKCS8`.
+
+ .. _PEM: http://www.ietf.org/rfc/rfc1421.txt
+ .. _`PEM encryption`: http://www.ietf.org/rfc/rfc1423.txt
+ .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
+ .. _OpenSSH: http://www.openssh.com/txt/rfc5656.txt
+ .. _RFC5480: https://tools.ietf.org/html/rfc5480
+ .. _RFC5915: http://www.ietf.org/rfc/rfc5915.txt
+
+ Returns:
+ A multi-line string (for PEM and OpenSSH) or bytes (for DER) with the encoded key.
+ """
+
+ args = kwargs.copy()
+ ext_format = args.pop("format")
+ if ext_format not in ("PEM", "DER", "OpenSSH"):
+ raise ValueError("Unknown format '%s'" % ext_format)
+
+ compress = args.pop("compress", False)
+
+ if self.has_private():
+ passphrase = args.pop("passphrase", None)
+ if is_string(passphrase):
+ passphrase = tobytes(passphrase)
+ if not passphrase:
+ raise ValueError("Empty passphrase")
+ use_pkcs8 = args.pop("use_pkcs8", True)
+ if ext_format == "PEM":
+ if use_pkcs8:
+ if passphrase:
+ return self._export_private_encrypted_pkcs8_in_clear_pem(passphrase, **args)
+ else:
+ return self._export_private_clear_pkcs8_in_clear_pem()
+ else:
+ return self._export_private_pem(passphrase, **args)
+ elif ext_format == "DER":
+ # DER
+ if passphrase and not use_pkcs8:
+ raise ValueError("Private keys can only be encrpyted with DER using PKCS#8")
+ if use_pkcs8:
+ return self._export_pkcs8(passphrase=passphrase, **args)
+ else:
+ return self._export_private_der()
+ else:
+ raise ValueError("Private keys cannot be exported in OpenSSH format")
+ else: # Public key
+ if args:
+ raise ValueError("Unexpected parameters: '%s'" % args)
+ if ext_format == "PEM":
+ return self._export_public_pem(compress)
+ elif ext_format == "DER":
+ return self._export_subjectPublicKeyInfo(compress)
+ else:
+ return self._export_openssh(compress)
+
+
+def generate(**kwargs):
+ """Generate a new private key on the given curve.
+
+ Args:
+
+ curve (string):
+ Mandatory. It must be a curve name defined in :numref:`curve_names`.
+
+ randfunc (callable):
+ Optional. The RNG to read randomness from.
+ If ``None``, :func:`Cryptodome.Random.get_random_bytes` is used.
+ """
+
+ curve_name = kwargs.pop("curve")
+ curve = _curves[curve_name]
+ randfunc = kwargs.pop("randfunc", get_random_bytes)
+ if kwargs:
+ raise TypeError("Unknown parameters: " + str(kwargs))
+
+ d = Integer.random_range(min_inclusive=1,
+ max_exclusive=curve.order,
+ randfunc=randfunc)
+
+ return EccKey(curve=curve_name, d=d)
+
+
+def construct(**kwargs):
+ """Build a new ECC key (private or public) starting
+ from some base components.
+
+ Args:
+
+ curve (string):
+ Mandatory. It must be a curve name defined in :numref:`curve_names`.
+
+ d (integer):
+ Only for a private key. It must be in the range ``[1..order-1]``.
+
+ point_x (integer):
+ Mandatory for a public key. X coordinate (affine) of the ECC point.
+
+ point_y (integer):
+ Mandatory for a public key. Y coordinate (affine) of the ECC point.
+
+ Returns:
+ :class:`EccKey` : a new ECC key object
+ """
+
+ curve_name = kwargs["curve"]
+ curve = _curves[curve_name]
+ point_x = kwargs.pop("point_x", None)
+ point_y = kwargs.pop("point_y", None)
+
+ if "point" in kwargs:
+ raise TypeError("Unknown keyword: point")
+
+ if None not in (point_x, point_y):
+ # ValueError is raised if the point is not on the curve
+ kwargs["point"] = EccPoint(point_x, point_y, curve_name)
+
+ # Validate that the private key matches the public one
+ d = kwargs.get("d", None)
+ if d is not None and "point" in kwargs:
+ pub_key = curve.G * d
+ if pub_key.xy != (point_x, point_y):
+ raise ValueError("Private and public ECC keys do not match")
+
+ return EccKey(**kwargs)
+
+
+def _import_public_der(curve_oid, ec_point):
+ """Convert an encoded EC point into an EccKey object
+
+ curve_name: string with the OID of the curve
+ ec_point: byte string with the EC point (not DER encoded)
+
+ """
+
+ for curve_name, curve in _curves.items():
+ if curve.oid == curve_oid:
+ break
+ else:
+ raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" % curve_oid)
+
+ # See 2.2 in RFC5480 and 2.3.3 in SEC1
+ # The first byte is:
+ # - 0x02: compressed, only X-coordinate, Y-coordinate is even
+ # - 0x03: compressed, only X-coordinate, Y-coordinate is odd
+ # - 0x04: uncompressed, X-coordinate is followed by Y-coordinate
+ #
+ # PAI is in theory encoded as 0x00.
+
+ modulus_bytes = curve.p.size_in_bytes()
+ point_type = bord(ec_point[0])
+
+ # Uncompressed point
+ if point_type == 0x04:
+ if len(ec_point) != (1 + 2 * modulus_bytes):
+ raise ValueError("Incorrect EC point length")
+ x = Integer.from_bytes(ec_point[1:modulus_bytes+1])
+ y = Integer.from_bytes(ec_point[modulus_bytes+1:])
+ # Compressed point
+ elif point_type in (0x02, 0x3):
+ if len(ec_point) != (1 + modulus_bytes):
+ raise ValueError("Incorrect EC point length")
+ x = Integer.from_bytes(ec_point[1:])
+ y = (x**3 - x*3 + curve.b).sqrt(curve.p) # Short Weierstrass
+ if point_type == 0x02 and y.is_odd():
+ y = curve.p - y
+ if point_type == 0x03 and y.is_even():
+ y = curve.p - y
+ else:
+ raise ValueError("Incorrect EC point encoding")
+
+ return construct(curve=curve_name, point_x=x, point_y=y)
+
+
+def _import_subjectPublicKeyInfo(encoded, *kwargs):
+ """Convert a subjectPublicKeyInfo into an EccKey object"""
+
+ # See RFC5480
+
+ # Parse the generic subjectPublicKeyInfo structure
+ oid, ec_point, params = _expand_subject_public_key_info(encoded)
+
+ # ec_point must be an encoded OCTET STRING
+ # params is encoded ECParameters
+
+ # We accept id-ecPublicKey, id-ecDH, id-ecMQV without making any
+ # distiction for now.
+
+ # Restrictions can be captured in the key usage certificate
+ # extension
+ unrestricted_oid = "1.2.840.10045.2.1"
+ ecdh_oid = "1.3.132.1.12"
+ ecmqv_oid = "1.3.132.1.13"
+
+ if oid not in (unrestricted_oid, ecdh_oid, ecmqv_oid):
+ raise UnsupportedEccFeature("Unsupported ECC purpose (OID: %s)" % oid)
+
+ # Parameters are mandatory for all three types
+ if not params:
+ raise ValueError("Missing ECC parameters")
+
+ # ECParameters ::= CHOICE {
+ # namedCurve OBJECT IDENTIFIER
+ # -- implicitCurve NULL
+ # -- specifiedCurve SpecifiedECDomain
+ # }
+ #
+ # implicitCurve and specifiedCurve are not supported (as per RFC)
+ curve_oid = DerObjectId().decode(params).value
+
+ return _import_public_der(curve_oid, ec_point)
+
+
+def _import_private_der(encoded, passphrase, curve_oid=None):
+
+ # See RFC5915 https://tools.ietf.org/html/rfc5915
+ #
+ # ECPrivateKey ::= SEQUENCE {
+ # version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
+ # privateKey OCTET STRING,
+ # parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
+ # publicKey [1] BIT STRING OPTIONAL
+ # }
+
+ private_key = DerSequence().decode(encoded, nr_elements=(3, 4))
+ if private_key[0] != 1:
+ raise ValueError("Incorrect ECC private key version")
+
+ try:
+ parameters = DerObjectId(explicit=0).decode(private_key[2]).value
+ if curve_oid is not None and parameters != curve_oid:
+ raise ValueError("Curve mismatch")
+ curve_oid = parameters
+ except ValueError:
+ pass
+
+ if curve_oid is None:
+ raise ValueError("No curve found")
+
+ for curve_name, curve in _curves.items():
+ if curve.oid == curve_oid:
+ break
+ else:
+ raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" % curve_oid)
+
+ scalar_bytes = DerOctetString().decode(private_key[1]).payload
+ modulus_bytes = curve.p.size_in_bytes()
+ if len(scalar_bytes) != modulus_bytes:
+ raise ValueError("Private key is too small")
+ d = Integer.from_bytes(scalar_bytes)
+
+ # Decode public key (if any)
+ if len(private_key) == 4:
+ public_key_enc = DerBitString(explicit=1).decode(private_key[3]).value
+ public_key = _import_public_der(curve_oid, public_key_enc)
+ point_x = public_key.pointQ.x
+ point_y = public_key.pointQ.y
+ else:
+ point_x = point_y = None
+
+ return construct(curve=curve_name, d=d, point_x=point_x, point_y=point_y)
+
+
+def _import_pkcs8(encoded, passphrase):
+ from Cryptodome.IO import PKCS8
+
+ # From RFC5915, Section 1:
+ #
+ # Distributing an EC private key with PKCS#8 [RFC5208] involves including:
+ # a) id-ecPublicKey, id-ecDH, or id-ecMQV (from [RFC5480]) with the
+ # namedCurve as the parameters in the privateKeyAlgorithm field; and
+ # b) ECPrivateKey in the PrivateKey field, which is an OCTET STRING.
+
+ algo_oid, private_key, params = PKCS8.unwrap(encoded, passphrase)
+
+ # We accept id-ecPublicKey, id-ecDH, id-ecMQV without making any
+ # distiction for now.
+ unrestricted_oid = "1.2.840.10045.2.1"
+ ecdh_oid = "1.3.132.1.12"
+ ecmqv_oid = "1.3.132.1.13"
+
+ if algo_oid not in (unrestricted_oid, ecdh_oid, ecmqv_oid):
+ raise UnsupportedEccFeature("Unsupported ECC purpose (OID: %s)" % algo_oid)
+
+ curve_oid = DerObjectId().decode(params).value
+
+ return _import_private_der(private_key, passphrase, curve_oid)
+
+
+def _import_x509_cert(encoded, *kwargs):
+
+ sp_info = _extract_subject_public_key_info(encoded)
+ return _import_subjectPublicKeyInfo(sp_info)
+
+
+def _import_der(encoded, passphrase):
+
+ try:
+ return _import_subjectPublicKeyInfo(encoded, passphrase)
+ except UnsupportedEccFeature as err:
+ raise err
+ except (ValueError, TypeError, IndexError):
+ pass
+
+ try:
+ return _import_x509_cert(encoded, passphrase)
+ except UnsupportedEccFeature as err:
+ raise err
+ except (ValueError, TypeError, IndexError):
+ pass
+
+ try:
+ return _import_private_der(encoded, passphrase)
+ except UnsupportedEccFeature as err:
+ raise err
+ except (ValueError, TypeError, IndexError):
+ pass
+
+ try:
+ return _import_pkcs8(encoded, passphrase)
+ except UnsupportedEccFeature as err:
+ raise err
+ except (ValueError, TypeError, IndexError):
+ pass
+
+ raise ValueError("Not an ECC DER key")
+
+
+def _import_openssh_public(encoded):
+ keystring = binascii.a2b_base64(encoded.split(b' ')[1])
+
+ keyparts = []
+ while len(keystring) > 4:
+ lk = struct.unpack(">I", keystring[:4])[0]
+ keyparts.append(keystring[4:4 + lk])
+ keystring = keystring[4 + lk:]
+
+ for curve_name, curve in _curves.items():
+ middle = tobytes(curve.openssh.split("-")[2])
+ if keyparts[1] == middle:
+ break
+ else:
+ raise ValueError("Unsupported ECC curve")
+
+ return _import_public_der(curve.oid, keyparts[2])
+
+
+def _import_openssh_private_ecc(data, password):
+
+ from ._openssh import (import_openssh_private_generic,
+ read_bytes, read_string, check_padding)
+
+ ssh_name, decrypted = import_openssh_private_generic(data, password)
+
+ name, decrypted = read_string(decrypted)
+ if name not in _curves:
+ raise UnsupportedEccFeature("Unsupported ECC curve %s" % name)
+ curve = _curves[name]
+ modulus_bytes = (curve.modulus_bits + 7) // 8
+
+ public_key, decrypted = read_bytes(decrypted)
+
+ if bord(public_key[0]) != 4:
+ raise ValueError("Only uncompressed OpenSSH EC keys are supported")
+ if len(public_key) != 2 * modulus_bytes + 1:
+ raise ValueError("Incorrect public key length")
+
+ point_x = Integer.from_bytes(public_key[1:1+modulus_bytes])
+ point_y = Integer.from_bytes(public_key[1+modulus_bytes:])
+ point = EccPoint(point_x, point_y, curve=name)
+
+ private_key, decrypted = read_bytes(decrypted)
+ d = Integer.from_bytes(private_key)
+
+ _, padded = read_string(decrypted) # Comment
+ check_padding(padded)
+
+ return EccKey(curve=name, d=d, point=point)
+
+
+def import_key(encoded, passphrase=None):
+ """Import an ECC key (public or private).
+
+ Args:
+ encoded (bytes or multi-line string):
+ The ECC key to import.
+
+ An ECC **public** key can be:
+
+ - An X.509 certificate, binary (DER) or ASCII (PEM)
+ - An X.509 ``subjectPublicKeyInfo``, binary (DER) or ASCII (PEM)
+ - An OpenSSH line (e.g. the content of ``~/.ssh/id_ecdsa``, ASCII)
+
+ An ECC **private** key can be:
+
+ - In binary format (DER, see section 3 of `RFC5915`_ or `PKCS#8`_)
+ - In ASCII format (PEM or `OpenSSH 6.5+`_)
+
+ Private keys can be in the clear or password-protected.
+
+ For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.
+
+ passphrase (byte string):
+ The passphrase to use for decrypting a private key.
+ Encryption may be applied protected at the PEM level or at the PKCS#8 level.
+ This parameter is ignored if the key in input is not encrypted.
+
+ Returns:
+ :class:`EccKey` : a new ECC key object
+
+ Raises:
+ ValueError: when the given key cannot be parsed (possibly because
+ the pass phrase is wrong).
+
+ .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
+ .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
+ .. _RFC5915: http://www.ietf.org/rfc/rfc5915.txt
+ .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
+ .. _`OpenSSH 6.5+`: https://flak.tedunangst.com/post/new-openssh-key-format-and-bcrypt-pbkdf
+ """
+
+ from Cryptodome.IO import PEM
+
+ encoded = tobytes(encoded)
+ if passphrase is not None:
+ passphrase = tobytes(passphrase)
+
+ # PEM
+ if encoded.startswith(b'-----BEGIN OPENSSH PRIVATE KEY'):
+ text_encoded = tostr(encoded)
+ openssh_encoded, marker, enc_flag = PEM.decode(text_encoded, passphrase)
+ result = _import_openssh_private_ecc(openssh_encoded, passphrase)
+ return result
+
+ elif encoded.startswith(b'-----'):
+
+ text_encoded = tostr(encoded)
+
+ # Remove any EC PARAMETERS section
+ # Ignore its content because the curve type must be already given in the key
+ if sys.version_info[:2] != (2, 6):
+ ecparams_start = "-----BEGIN EC PARAMETERS-----"
+ ecparams_end = "-----END EC PARAMETERS-----"
+ text_encoded = re.sub(ecparams_start + ".*?" + ecparams_end, "",
+ text_encoded,
+ flags=re.DOTALL)
+
+ der_encoded, marker, enc_flag = PEM.decode(text_encoded, passphrase)
+ if enc_flag:
+ passphrase = None
+ try:
+ result = _import_der(der_encoded, passphrase)
+ except UnsupportedEccFeature as uef:
+ raise uef
+ except ValueError:
+ raise ValueError("Invalid DER encoding inside the PEM file")
+ return result
+
+ # OpenSSH
+ if encoded.startswith(b'ecdsa-sha2-'):
+ return _import_openssh_public(encoded)
+
+ # DER
+ if len(encoded) > 0 and bord(encoded[0]) == 0x30:
+ return _import_der(encoded, passphrase)
+
+ raise ValueError("ECC key format is not supported")
+
+
+if __name__ == "__main__":
+
+ import time
+
+ d = 0xc51e4753afdec1e6b6c6a5b992f43f8dd0c7a8933072708b6522468b2ffb06fd
+
+ point = _curves['p256'].G.copy()
+ count = 3000
+
+ start = time.time()
+ for x in range(count):
+ pointX = point * d
+ print("(P-256 G)", (time.time() - start) / count * 1000, "ms")
+
+ start = time.time()
+ for x in range(count):
+ pointX = pointX * d
+ print("(P-256 arbitrary point)", (time.time() - start) / count * 1000, "ms")
diff --git a/frozen_deps/Cryptodome/PublicKey/ECC.pyi b/frozen_deps/Cryptodome/PublicKey/ECC.pyi
new file mode 100644
index 0000000..b38b337
--- /dev/null
+++ b/frozen_deps/Cryptodome/PublicKey/ECC.pyi
@@ -0,0 +1,62 @@
+from typing import Union, Callable, Optional, NamedTuple, List, Tuple, Dict, NamedTuple, Any
+
+from Cryptodome.Math.Numbers import Integer
+
+RNG = Callable[[int], bytes]
+
+class UnsupportedEccFeature(ValueError): ...
+class EccPoint(object):
+ def __init__(self, x: Union[int, Integer], y: Union[int, Integer], curve: Optional[str] = ...) -> None: ...
+ def set(self, point: EccPoint) -> EccPoint: ...
+ def __eq__(self, point: object) -> bool: ...
+ def __neg__(self) -> EccPoint: ...
+ def copy(self) -> EccPoint: ...
+ def is_point_at_infinity(self) -> bool: ...
+ def point_at_infinity(self) -> EccPoint: ...
+ @property
+ def x(self) -> int: ...
+ @property
+ def y(self) -> int: ...
+ @property
+ def xy(self) -> Tuple[int, int]: ...
+ def size_in_bytes(self) -> int: ...
+ def size_in_bits(self) -> int: ...
+ def double(self) -> EccPoint: ...
+ def __iadd__(self, point: EccPoint) -> EccPoint: ...
+ def __add__(self, point: EccPoint) -> EccPoint: ...
+ def __imul__(self, scalar: int) -> EccPoint: ...
+ def __mul__(self, scalar: int) -> EccPoint: ...
+
+class EccKey(object):
+ curve: str
+ def __init__(self, *, curve: str = ..., d: int = ..., point: EccPoint = ...) -> None: ...
+ def __eq__(self, other: object) -> bool: ...
+ def __repr__(self) -> str: ...
+ def has_private(self) -> bool: ...
+ @property
+ def d(self) -> int: ...
+ @property
+ def pointQ(self) -> EccPoint: ...
+ def public_key(self) -> EccKey: ...
+ def export_key(self, **kwargs: Union[str, bytes, bool]) -> str: ...
+
+
+_Curve = NamedTuple("_Curve", [('p', Integer),
+ ('order', Integer),
+ ('b', Integer),
+ ('Gx', Integer),
+ ('Gy', Integer),
+ ('G', EccPoint),
+ ('modulus_bits', int),
+ ('oid', str),
+ ('context', Any),
+ ('desc', str),
+ ('openssh', str),
+ ])
+
+_curves : Dict[str, _Curve]
+
+
+def generate(**kwargs: Union[str, RNG]) -> EccKey: ...
+def construct(**kwargs: Union[str, int]) -> EccKey: ...
+def import_key(encoded: Union[bytes, str], passphrase: Optional[str]=None) -> EccKey: ...
diff --git a/frozen_deps/Cryptodome/PublicKey/ElGamal.py b/frozen_deps/Cryptodome/PublicKey/ElGamal.py
new file mode 100644
index 0000000..95c219e
--- /dev/null
+++ b/frozen_deps/Cryptodome/PublicKey/ElGamal.py
@@ -0,0 +1,286 @@
+#
+# ElGamal.py : ElGamal encryption/decryption and signatures
+#
+# Part of the Python Cryptography Toolkit
+#
+# Originally written by: A.M. Kuchling
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+__all__ = ['generate', 'construct', 'ElGamalKey']
+
+from Cryptodome import Random
+from Cryptodome.Math.Primality import ( generate_probable_safe_prime,
+ test_probable_prime, COMPOSITE )
+from Cryptodome.Math.Numbers import Integer
+
+# Generate an ElGamal key with N bits
+def generate(bits, randfunc):
+ """Randomly generate a fresh, new ElGamal key.
+
+ The key will be safe for use for both encryption and signature
+ (although it should be used for **only one** purpose).
+
+ Args:
+ bits (int):
+ Key length, or size (in bits) of the modulus *p*.
+ The recommended value is 2048.
+ randfunc (callable):
+ Random number generation function; it should accept
+ a single integer *N* and return a string of random
+ *N* random bytes.
+
+ Return:
+ an :class:`ElGamalKey` object
+ """
+
+ obj=ElGamalKey()
+
+ # Generate a safe prime p
+ # See Algorithm 4.86 in Handbook of Applied Cryptography
+ obj.p = generate_probable_safe_prime(exact_bits=bits, randfunc=randfunc)
+ q = (obj.p - 1) >> 1
+
+ # Generate generator g
+ while 1:
+ # Choose a square residue; it will generate a cyclic group of order q.
+ obj.g = pow(Integer.random_range(min_inclusive=2,
+ max_exclusive=obj.p,
+ randfunc=randfunc), 2, obj.p)
+
+ # We must avoid g=2 because of Bleichenbacher's attack described
+ # in "Generating ElGamal signatures without knowning the secret key",
+ # 1996
+ if obj.g in (1, 2):
+ continue
+
+ # Discard g if it divides p-1 because of the attack described
+ # in Note 11.67 (iii) in HAC
+ if (obj.p - 1) % obj.g == 0:
+ continue
+
+ # g^{-1} must not divide p-1 because of Khadir's attack
+ # described in "Conditions of the generator for forging ElGamal
+ # signature", 2011
+ ginv = obj.g.inverse(obj.p)
+ if (obj.p - 1) % ginv == 0:
+ continue
+
+ # Found
+ break
+
+ # Generate private key x
+ obj.x = Integer.random_range(min_inclusive=2,
+ max_exclusive=obj.p-1,
+ randfunc=randfunc)
+ # Generate public key y
+ obj.y = pow(obj.g, obj.x, obj.p)
+ return obj
+
+def construct(tup):
+ r"""Construct an ElGamal key from a tuple of valid ElGamal components.
+
+ The modulus *p* must be a prime.
+ The following conditions must apply:
+
+ .. math::
+
+ \begin{align}
+ &1 < g < p-1 \\
+ &g^{p-1} = 1 \text{ mod } 1 \\
+ &1 < x < p-1 \\
+ &g^x = y \text{ mod } p
+ \end{align}
+
+ Args:
+ tup (tuple):
+ A tuple with either 3 or 4 integers,
+ in the following order:
+
+ 1. Modulus (*p*).
+ 2. Generator (*g*).
+ 3. Public key (*y*).
+ 4. Private key (*x*). Optional.
+
+ Raises:
+ ValueError: when the key being imported fails the most basic ElGamal validity checks.
+
+ Returns:
+ an :class:`ElGamalKey` object
+ """
+
+ obj=ElGamalKey()
+ if len(tup) not in [3,4]:
+ raise ValueError('argument for construct() wrong length')
+ for i in range(len(tup)):
+ field = obj._keydata[i]
+ setattr(obj, field, Integer(tup[i]))
+
+ fmt_error = test_probable_prime(obj.p) == COMPOSITE
+ fmt_error |= obj.g<=1 or obj.g>=obj.p
+ fmt_error |= pow(obj.g, obj.p-1, obj.p)!=1
+ fmt_error |= obj.y<1 or obj.y>=obj.p
+ if len(tup)==4:
+ fmt_error |= obj.x<=1 or obj.x>=obj.p
+ fmt_error |= pow(obj.g, obj.x, obj.p)!=obj.y
+
+ if fmt_error:
+ raise ValueError("Invalid ElGamal key components")
+
+ return obj
+
+class ElGamalKey(object):
+ r"""Class defining an ElGamal key.
+ Do not instantiate directly.
+ Use :func:`generate` or :func:`construct` instead.
+
+ :ivar p: Modulus
+ :vartype d: integer
+
+ :ivar g: Generator
+ :vartype e: integer
+
+ :ivar y: Public key component
+ :vartype y: integer
+
+ :ivar x: Private key component
+ :vartype x: integer
+ """
+
+ #: Dictionary of ElGamal parameters.
+ #:
+ #: A public key will only have the following entries:
+ #:
+ #: - **y**, the public key.
+ #: - **g**, the generator.
+ #: - **p**, the modulus.
+ #:
+ #: A private key will also have:
+ #:
+ #: - **x**, the private key.
+ _keydata=['p', 'g', 'y', 'x']
+
+ def __init__(self, randfunc=None):
+ if randfunc is None:
+ randfunc = Random.new().read
+ self._randfunc = randfunc
+
+ def _encrypt(self, M, K):
+ a=pow(self.g, K, self.p)
+ b=( pow(self.y, K, self.p)*M ) % self.p
+ return [int(a), int(b)]
+
+ def _decrypt(self, M):
+ if (not hasattr(self, 'x')):
+ raise TypeError('Private key not available in this object')
+ r = Integer.random_range(min_inclusive=2,
+ max_exclusive=self.p-1,
+ randfunc=self._randfunc)
+ a_blind = (pow(self.g, r, self.p) * M[0]) % self.p
+ ax=pow(a_blind, self.x, self.p)
+ plaintext_blind = (ax.inverse(self.p) * M[1] ) % self.p
+ plaintext = (plaintext_blind * pow(self.y, r, self.p)) % self.p
+ return int(plaintext)
+
+ def _sign(self, M, K):
+ if (not hasattr(self, 'x')):
+ raise TypeError('Private key not available in this object')
+ p1=self.p-1
+ K = Integer(K)
+ if (K.gcd(p1)!=1):
+ raise ValueError('Bad K value: GCD(K,p-1)!=1')
+ a=pow(self.g, K, self.p)
+ t=(Integer(M)-self.x*a) % p1
+ while t<0: t=t+p1
+ b=(t*K.inverse(p1)) % p1
+ return [int(a), int(b)]
+
+ def _verify(self, M, sig):
+ sig = [Integer(x) for x in sig]
+ if sig[0]<1 or sig[0]>self.p-1:
+ return 0
+ v1=pow(self.y, sig[0], self.p)
+ v1=(v1*pow(sig[0], sig[1], self.p)) % self.p
+ v2=pow(self.g, M, self.p)
+ if v1==v2:
+ return 1
+ return 0
+
+ def has_private(self):
+ """Whether this is an ElGamal private key"""
+
+ if hasattr(self, 'x'):
+ return 1
+ else:
+ return 0
+
+ def can_encrypt(self):
+ return True
+
+ def can_sign(self):
+ return True
+
+ def publickey(self):
+ """A matching ElGamal public key.
+
+ Returns:
+ a new :class:`ElGamalKey` object
+ """
+ return construct((self.p, self.g, self.y))
+
+ def __eq__(self, other):
+ if bool(self.has_private()) != bool(other.has_private()):
+ return False
+
+ result = True
+ for comp in self._keydata:
+ result = result and (getattr(self.key, comp, None) ==
+ getattr(other.key, comp, None))
+ return result
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def __getstate__(self):
+ # ElGamal key is not pickable
+ from pickle import PicklingError
+ raise PicklingError
+
+ # Methods defined in PyCryptodome that we don't support anymore
+
+ def sign(self, M, K):
+ raise NotImplementedError
+
+ def verify(self, M, signature):
+ raise NotImplementedError
+
+ def encrypt(self, plaintext, K):
+ raise NotImplementedError
+
+ def decrypt(self, ciphertext):
+ raise NotImplementedError
+
+ def blind(self, M, B):
+ raise NotImplementedError
+
+ def unblind(self, M, B):
+ raise NotImplementedError
+
+ def size(self):
+ raise NotImplementedError
diff --git a/frozen_deps/Cryptodome/PublicKey/ElGamal.pyi b/frozen_deps/Cryptodome/PublicKey/ElGamal.pyi
new file mode 100644
index 0000000..9048531
--- /dev/null
+++ b/frozen_deps/Cryptodome/PublicKey/ElGamal.pyi
@@ -0,0 +1,18 @@
+from typing import Callable, Union, Tuple, Optional
+
+__all__ = ['generate', 'construct', 'ElGamalKey']
+
+RNG = Callable[[int], bytes]
+
+def generate(bits: int, randfunc: RNG) -> ElGamalKey: ...
+def construct(tup: Union[Tuple[int, int, int], Tuple[int, int, int, int]]) -> ElGamalKey: ...
+
+class ElGamalKey(object):
+ def __init__(self, randfunc: Optional[RNG]=None) -> None: ...
+ def has_private(self) -> bool: ...
+ def can_encrypt(self) -> bool: ...
+ def can_sign(self) -> bool: ...
+ def publickey(self) -> ElGamalKey: ...
+ def __eq__(self, other: object) -> bool: ...
+ def __ne__(self, other: object) -> bool: ...
+ def __getstate__(self) -> None: ...
diff --git a/frozen_deps/Cryptodome/PublicKey/RSA.py b/frozen_deps/Cryptodome/PublicKey/RSA.py
new file mode 100644
index 0000000..27331ca
--- /dev/null
+++ b/frozen_deps/Cryptodome/PublicKey/RSA.py
@@ -0,0 +1,796 @@
+# -*- coding: utf-8 -*-
+# ===================================================================
+#
+# Copyright (c) 2016, Legrandin <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+__all__ = ['generate', 'construct', 'import_key',
+ 'RsaKey', 'oid']
+
+import binascii
+import struct
+
+from Cryptodome import Random
+from Cryptodome.Util.py3compat import tobytes, bord, tostr
+from Cryptodome.Util.asn1 import DerSequence
+
+from Cryptodome.Math.Numbers import Integer
+from Cryptodome.Math.Primality import (test_probable_prime,
+ generate_probable_prime, COMPOSITE)
+
+from Cryptodome.PublicKey import (_expand_subject_public_key_info,
+ _create_subject_public_key_info,
+ _extract_subject_public_key_info)
+
+
+class RsaKey(object):
+ r"""Class defining an actual RSA key.
+ Do not instantiate directly.
+ Use :func:`generate`, :func:`construct` or :func:`import_key` instead.
+
+ :ivar n: RSA modulus
+ :vartype n: integer
+
+ :ivar e: RSA public exponent
+ :vartype e: integer
+
+ :ivar d: RSA private exponent
+ :vartype d: integer
+
+ :ivar p: First factor of the RSA modulus
+ :vartype p: integer
+
+ :ivar q: Second factor of the RSA modulus
+ :vartype q: integer
+
+ :ivar u: Chinese remainder component (:math:`p^{-1} \text{mod } q`)
+ :vartype q: integer
+ """
+
+ def __init__(self, **kwargs):
+ """Build an RSA key.
+
+ :Keywords:
+ n : integer
+ The modulus.
+ e : integer
+ The public exponent.
+ d : integer
+ The private exponent. Only required for private keys.
+ p : integer
+ The first factor of the modulus. Only required for private keys.
+ q : integer
+ The second factor of the modulus. Only required for private keys.
+ u : integer
+ The CRT coefficient (inverse of p modulo q). Only required for
+ private keys.
+ """
+
+ input_set = set(kwargs.keys())
+ public_set = set(('n', 'e'))
+ private_set = public_set | set(('p', 'q', 'd', 'u'))
+ if input_set not in (private_set, public_set):
+ raise ValueError("Some RSA components are missing")
+ for component, value in kwargs.items():
+ setattr(self, "_" + component, value)
+ if input_set == private_set:
+ self._dp = self._d % (self._p - 1) # = (e⁻¹) mod (p-1)
+ self._dq = self._d % (self._q - 1) # = (e⁻¹) mod (q-1)
+
+ @property
+ def n(self):
+ return int(self._n)
+
+ @property
+ def e(self):
+ return int(self._e)
+
+ @property
+ def d(self):
+ if not self.has_private():
+ raise AttributeError("No private exponent available for public keys")
+ return int(self._d)
+
+ @property
+ def p(self):
+ if not self.has_private():
+ raise AttributeError("No CRT component 'p' available for public keys")
+ return int(self._p)
+
+ @property
+ def q(self):
+ if not self.has_private():
+ raise AttributeError("No CRT component 'q' available for public keys")
+ return int(self._q)
+
+ @property
+ def u(self):
+ if not self.has_private():
+ raise AttributeError("No CRT component 'u' available for public keys")
+ return int(self._u)
+
+ def size_in_bits(self):
+ """Size of the RSA modulus in bits"""
+ return self._n.size_in_bits()
+
+ def size_in_bytes(self):
+ """The minimal amount of bytes that can hold the RSA modulus"""
+ return (self._n.size_in_bits() - 1) // 8 + 1
+
+ def _encrypt(self, plaintext):
+ if not 0 <= plaintext < self._n:
+ raise ValueError("Plaintext too large")
+ return int(pow(Integer(plaintext), self._e, self._n))
+
+ def _decrypt(self, ciphertext):
+ if not 0 <= ciphertext < self._n:
+ raise ValueError("Ciphertext too large")
+ if not self.has_private():
+ raise TypeError("This is not a private key")
+
+ # Blinded RSA decryption (to prevent timing attacks):
+ # Step 1: Generate random secret blinding factor r,
+ # such that 0 < r < n-1
+ r = Integer.random_range(min_inclusive=1, max_exclusive=self._n)
+ # Step 2: Compute c' = c * r**e mod n
+ cp = Integer(ciphertext) * pow(r, self._e, self._n) % self._n
+ # Step 3: Compute m' = c'**d mod n (normal RSA decryption)
+ m1 = pow(cp, self._dp, self._p)
+ m2 = pow(cp, self._dq, self._q)
+ h = ((m2 - m1) * self._u) % self._q
+ mp = h * self._p + m1
+ # Step 4: Compute m = m**(r-1) mod n
+ result = (r.inverse(self._n) * mp) % self._n
+ # Verify no faults occurred
+ if ciphertext != pow(result, self._e, self._n):
+ raise ValueError("Fault detected in RSA decryption")
+ return result
+
+ def has_private(self):
+ """Whether this is an RSA private key"""
+
+ return hasattr(self, "_d")
+
+ def can_encrypt(self): # legacy
+ return True
+
+ def can_sign(self): # legacy
+ return True
+
+ def publickey(self):
+ """A matching RSA public key.
+
+ Returns:
+ a new :class:`RsaKey` object
+ """
+ return RsaKey(n=self._n, e=self._e)
+
+ def __eq__(self, other):
+ if self.has_private() != other.has_private():
+ return False
+ if self.n != other.n or self.e != other.e:
+ return False
+ if not self.has_private():
+ return True
+ return (self.d == other.d)
+
+ def __ne__(self, other):
+ return not (self == other)
+
+ def __getstate__(self):
+ # RSA key is not pickable
+ from pickle import PicklingError
+ raise PicklingError
+
+ def __repr__(self):
+ if self.has_private():
+ extra = ", d=%d, p=%d, q=%d, u=%d" % (int(self._d), int(self._p),
+ int(self._q), int(self._u))
+ else:
+ extra = ""
+ return "RsaKey(n=%d, e=%d%s)" % (int(self._n), int(self._e), extra)
+
+ def __str__(self):
+ if self.has_private():
+ key_type = "Private"
+ else:
+ key_type = "Public"
+ return "%s RSA key at 0x%X" % (key_type, id(self))
+
+ def export_key(self, format='PEM', passphrase=None, pkcs=1,
+ protection=None, randfunc=None):
+ """Export this RSA key.
+
+ Args:
+ format (string):
+ The format to use for wrapping the key:
+
+ - *'PEM'*. (*Default*) Text encoding, done according to `RFC1421`_/`RFC1423`_.
+ - *'DER'*. Binary encoding.
+ - *'OpenSSH'*. Textual encoding, done according to OpenSSH specification.
+ Only suitable for public keys (not private keys).
+
+ passphrase (string):
+ (*For private keys only*) The pass phrase used for protecting the output.
+
+ pkcs (integer):
+ (*For private keys only*) The ASN.1 structure to use for
+ serializing the key. Note that even in case of PEM
+ encoding, there is an inner ASN.1 DER structure.
+
+ With ``pkcs=1`` (*default*), the private key is encoded in a
+ simple `PKCS#1`_ structure (``RSAPrivateKey``).
+
+ With ``pkcs=8``, the private key is encoded in a `PKCS#8`_ structure
+ (``PrivateKeyInfo``).
+
+ .. note::
+ This parameter is ignored for a public key.
+ For DER and PEM, an ASN.1 DER ``SubjectPublicKeyInfo``
+ structure is always used.
+
+ protection (string):
+ (*For private keys only*)
+ The encryption scheme to use for protecting the private key.
+
+ If ``None`` (default), the behavior depends on :attr:`format`:
+
+ - For *'DER'*, the *PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC*
+ scheme is used. The following operations are performed:
+
+ 1. A 16 byte Triple DES key is derived from the passphrase
+ using :func:`Cryptodome.Protocol.KDF.PBKDF2` with 8 bytes salt,
+ and 1 000 iterations of :mod:`Cryptodome.Hash.HMAC`.
+ 2. The private key is encrypted using CBC.
+ 3. The encrypted key is encoded according to PKCS#8.
+
+ - For *'PEM'*, the obsolete PEM encryption scheme is used.
+ It is based on MD5 for key derivation, and Triple DES for encryption.
+
+ Specifying a value for :attr:`protection` is only meaningful for PKCS#8
+ (that is, ``pkcs=8``) and only if a pass phrase is present too.
+
+ The supported schemes for PKCS#8 are listed in the
+ :mod:`Cryptodome.IO.PKCS8` module (see :attr:`wrap_algo` parameter).
+
+ randfunc (callable):
+ A function that provides random bytes. Only used for PEM encoding.
+ The default is :func:`Cryptodome.Random.get_random_bytes`.
+
+ Returns:
+ byte string: the encoded key
+
+ Raises:
+ ValueError:when the format is unknown or when you try to encrypt a private
+ key with *DER* format and PKCS#1.
+
+ .. warning::
+ If you don't provide a pass phrase, the private key will be
+ exported in the clear!
+
+ .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
+ .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
+ .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt
+ .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
+ """
+
+ if passphrase is not None:
+ passphrase = tobytes(passphrase)
+
+ if randfunc is None:
+ randfunc = Random.get_random_bytes
+
+ if format == 'OpenSSH':
+ e_bytes, n_bytes = [x.to_bytes() for x in (self._e, self._n)]
+ if bord(e_bytes[0]) & 0x80:
+ e_bytes = b'\x00' + e_bytes
+ if bord(n_bytes[0]) & 0x80:
+ n_bytes = b'\x00' + n_bytes
+ keyparts = [b'ssh-rsa', e_bytes, n_bytes]
+ keystring = b''.join([struct.pack(">I", len(kp)) + kp for kp in keyparts])
+ return b'ssh-rsa ' + binascii.b2a_base64(keystring)[:-1]
+
+ # DER format is always used, even in case of PEM, which simply
+ # encodes it into BASE64.
+ if self.has_private():
+ binary_key = DerSequence([0,
+ self.n,
+ self.e,
+ self.d,
+ self.p,
+ self.q,
+ self.d % (self.p-1),
+ self.d % (self.q-1),
+ Integer(self.q).inverse(self.p)
+ ]).encode()
+ if pkcs == 1:
+ key_type = 'RSA PRIVATE KEY'
+ if format == 'DER' and passphrase:
+ raise ValueError("PKCS#1 private key cannot be encrypted")
+ else: # PKCS#8
+ from Cryptodome.IO import PKCS8
+
+ if format == 'PEM' and protection is None:
+ key_type = 'PRIVATE KEY'
+ binary_key = PKCS8.wrap(binary_key, oid, None)
+ else:
+ key_type = 'ENCRYPTED PRIVATE KEY'
+ if not protection:
+ protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC'
+ binary_key = PKCS8.wrap(binary_key, oid,
+ passphrase, protection)
+ passphrase = None
+ else:
+ key_type = "PUBLIC KEY"
+ binary_key = _create_subject_public_key_info(oid,
+ DerSequence([self.n,
+ self.e])
+ )
+
+ if format == 'DER':
+ return binary_key
+ if format == 'PEM':
+ from Cryptodome.IO import PEM
+
+ pem_str = PEM.encode(binary_key, key_type, passphrase, randfunc)
+ return tobytes(pem_str)
+
+ raise ValueError("Unknown key format '%s'. Cannot export the RSA key." % format)
+
+ # Backward compatibility
+ exportKey = export_key
+
+ # Methods defined in PyCryptodome that we don't support anymore
+ def sign(self, M, K):
+ raise NotImplementedError("Use module Cryptodome.Signature.pkcs1_15 instead")
+
+ def verify(self, M, signature):
+ raise NotImplementedError("Use module Cryptodome.Signature.pkcs1_15 instead")
+
+ def encrypt(self, plaintext, K):
+ raise NotImplementedError("Use module Cryptodome.Cipher.PKCS1_OAEP instead")
+
+ def decrypt(self, ciphertext):
+ raise NotImplementedError("Use module Cryptodome.Cipher.PKCS1_OAEP instead")
+
+ def blind(self, M, B):
+ raise NotImplementedError
+
+ def unblind(self, M, B):
+ raise NotImplementedError
+
+ def size(self):
+ raise NotImplementedError
+
+
+def generate(bits, randfunc=None, e=65537):
+ """Create a new RSA key pair.
+
+ The algorithm closely follows NIST `FIPS 186-4`_ in its
+ sections B.3.1 and B.3.3. The modulus is the product of
+ two non-strong probable primes.
+ Each prime passes a suitable number of Miller-Rabin tests
+ with random bases and a single Lucas test.
+
+ Args:
+ bits (integer):
+ Key length, or size (in bits) of the RSA modulus.
+ It must be at least 1024, but **2048 is recommended.**
+ The FIPS standard only defines 1024, 2048 and 3072.
+ randfunc (callable):
+ Function that returns random bytes.
+ The default is :func:`Cryptodome.Random.get_random_bytes`.
+ e (integer):
+ Public RSA exponent. It must be an odd positive integer.
+ It is typically a small number with very few ones in its
+ binary representation.
+ The FIPS standard requires the public exponent to be
+ at least 65537 (the default).
+
+ Returns: an RSA key object (:class:`RsaKey`, with private key).
+
+ .. _FIPS 186-4: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
+ """
+
+ if bits < 1024:
+ raise ValueError("RSA modulus length must be >= 1024")
+ if e % 2 == 0 or e < 3:
+ raise ValueError("RSA public exponent must be a positive, odd integer larger than 2.")
+
+ if randfunc is None:
+ randfunc = Random.get_random_bytes
+
+ d = n = Integer(1)
+ e = Integer(e)
+
+ while n.size_in_bits() != bits and d < (1 << (bits // 2)):
+ # Generate the prime factors of n: p and q.
+ # By construciton, their product is always
+ # 2^{bits-1} < p*q < 2^bits.
+ size_q = bits // 2
+ size_p = bits - size_q
+
+ min_p = min_q = (Integer(1) << (2 * size_q - 1)).sqrt()
+ if size_q != size_p:
+ min_p = (Integer(1) << (2 * size_p - 1)).sqrt()
+
+ def filter_p(candidate):
+ return candidate > min_p and (candidate - 1).gcd(e) == 1
+
+ p = generate_probable_prime(exact_bits=size_p,
+ randfunc=randfunc,
+ prime_filter=filter_p)
+
+ min_distance = Integer(1) << (bits // 2 - 100)
+
+ def filter_q(candidate):
+ return (candidate > min_q and
+ (candidate - 1).gcd(e) == 1 and
+ abs(candidate - p) > min_distance)
+
+ q = generate_probable_prime(exact_bits=size_q,
+ randfunc=randfunc,
+ prime_filter=filter_q)
+
+ n = p * q
+ lcm = (p - 1).lcm(q - 1)
+ d = e.inverse(lcm)
+
+ if p > q:
+ p, q = q, p
+
+ u = p.inverse(q)
+
+ return RsaKey(n=n, e=e, d=d, p=p, q=q, u=u)
+
+
+def construct(rsa_components, consistency_check=True):
+ r"""Construct an RSA key from a tuple of valid RSA components.
+
+ The modulus **n** must be the product of two primes.
+ The public exponent **e** must be odd and larger than 1.
+
+ In case of a private key, the following equations must apply:
+
+ .. math::
+
+ \begin{align}
+ p*q &= n \\
+ e*d &\equiv 1 ( \text{mod lcm} [(p-1)(q-1)]) \\
+ p*u &\equiv 1 ( \text{mod } q)
+ \end{align}
+
+ Args:
+ rsa_components (tuple):
+ A tuple of integers, with at least 2 and no
+ more than 6 items. The items come in the following order:
+
+ 1. RSA modulus *n*.
+ 2. Public exponent *e*.
+ 3. Private exponent *d*.
+ Only required if the key is private.
+ 4. First factor of *n* (*p*).
+ Optional, but the other factor *q* must also be present.
+ 5. Second factor of *n* (*q*). Optional.
+ 6. CRT coefficient *q*, that is :math:`p^{-1} \text{mod }q`. Optional.
+
+ consistency_check (boolean):
+ If ``True``, the library will verify that the provided components
+ fulfil the main RSA properties.
+
+ Raises:
+ ValueError: when the key being imported fails the most basic RSA validity checks.
+
+ Returns: An RSA key object (:class:`RsaKey`).
+ """
+
+ class InputComps(object):
+ pass
+
+ input_comps = InputComps()
+ for (comp, value) in zip(('n', 'e', 'd', 'p', 'q', 'u'), rsa_components):
+ setattr(input_comps, comp, Integer(value))
+
+ n = input_comps.n
+ e = input_comps.e
+ if not hasattr(input_comps, 'd'):
+ key = RsaKey(n=n, e=e)
+ else:
+ d = input_comps.d
+ if hasattr(input_comps, 'q'):
+ p = input_comps.p
+ q = input_comps.q
+ else:
+ # Compute factors p and q from the private exponent d.
+ # We assume that n has no more than two factors.
+ # See 8.2.2(i) in Handbook of Applied Cryptography.
+ ktot = d * e - 1
+ # The quantity d*e-1 is a multiple of phi(n), even,
+ # and can be represented as t*2^s.
+ t = ktot
+ while t % 2 == 0:
+ t //= 2
+ # Cycle through all multiplicative inverses in Zn.
+ # The algorithm is non-deterministic, but there is a 50% chance
+ # any candidate a leads to successful factoring.
+ # See "Digitalized Signatures and Public Key Functions as Intractable
+ # as Factorization", M. Rabin, 1979
+ spotted = False
+ a = Integer(2)
+ while not spotted and a < 100:
+ k = Integer(t)
+ # Cycle through all values a^{t*2^i}=a^k
+ while k < ktot:
+ cand = pow(a, k, n)
+ # Check if a^k is a non-trivial root of unity (mod n)
+ if cand != 1 and cand != (n - 1) and pow(cand, 2, n) == 1:
+ # We have found a number such that (cand-1)(cand+1)=0 (mod n).
+ # Either of the terms divides n.
+ p = Integer(n).gcd(cand + 1)
+ spotted = True
+ break
+ k *= 2
+ # This value was not any good... let's try another!
+ a += 2
+ if not spotted:
+ raise ValueError("Unable to compute factors p and q from exponent d.")
+ # Found !
+ assert ((n % p) == 0)
+ q = n // p
+
+ if hasattr(input_comps, 'u'):
+ u = input_comps.u
+ else:
+ u = p.inverse(q)
+
+ # Build key object
+ key = RsaKey(n=n, e=e, d=d, p=p, q=q, u=u)
+
+ # Verify consistency of the key
+ if consistency_check:
+
+ # Modulus and public exponent must be coprime
+ if e <= 1 or e >= n:
+ raise ValueError("Invalid RSA public exponent")
+ if Integer(n).gcd(e) != 1:
+ raise ValueError("RSA public exponent is not coprime to modulus")
+
+ # For RSA, modulus must be odd
+ if not n & 1:
+ raise ValueError("RSA modulus is not odd")
+
+ if key.has_private():
+ # Modulus and private exponent must be coprime
+ if d <= 1 or d >= n:
+ raise ValueError("Invalid RSA private exponent")
+ if Integer(n).gcd(d) != 1:
+ raise ValueError("RSA private exponent is not coprime to modulus")
+ # Modulus must be product of 2 primes
+ if p * q != n:
+ raise ValueError("RSA factors do not match modulus")
+ if test_probable_prime(p) == COMPOSITE:
+ raise ValueError("RSA factor p is composite")
+ if test_probable_prime(q) == COMPOSITE:
+ raise ValueError("RSA factor q is composite")
+ # See Carmichael theorem
+ phi = (p - 1) * (q - 1)
+ lcm = phi // (p - 1).gcd(q - 1)
+ if (e * d % int(lcm)) != 1:
+ raise ValueError("Invalid RSA condition")
+ if hasattr(key, 'u'):
+ # CRT coefficient
+ if u <= 1 or u >= q:
+ raise ValueError("Invalid RSA component u")
+ if (p * u % q) != 1:
+ raise ValueError("Invalid RSA component u with p")
+
+ return key
+
+
+def _import_pkcs1_private(encoded, *kwargs):
+ # RSAPrivateKey ::= SEQUENCE {
+ # version Version,
+ # modulus INTEGER, -- n
+ # publicExponent INTEGER, -- e
+ # privateExponent INTEGER, -- d
+ # prime1 INTEGER, -- p
+ # prime2 INTEGER, -- q
+ # exponent1 INTEGER, -- d mod (p-1)
+ # exponent2 INTEGER, -- d mod (q-1)
+ # coefficient INTEGER -- (inverse of q) mod p
+ # }
+ #
+ # Version ::= INTEGER
+ der = DerSequence().decode(encoded, nr_elements=9, only_ints_expected=True)
+ if der[0] != 0:
+ raise ValueError("No PKCS#1 encoding of an RSA private key")
+ return construct(der[1:6] + [Integer(der[4]).inverse(der[5])])
+
+
+def _import_pkcs1_public(encoded, *kwargs):
+ # RSAPublicKey ::= SEQUENCE {
+ # modulus INTEGER, -- n
+ # publicExponent INTEGER -- e
+ # }
+ der = DerSequence().decode(encoded, nr_elements=2, only_ints_expected=True)
+ return construct(der)
+
+
+def _import_subjectPublicKeyInfo(encoded, *kwargs):
+
+ algoid, encoded_key, params = _expand_subject_public_key_info(encoded)
+ if algoid != oid or params is not None:
+ raise ValueError("No RSA subjectPublicKeyInfo")
+ return _import_pkcs1_public(encoded_key)
+
+
+def _import_x509_cert(encoded, *kwargs):
+
+ sp_info = _extract_subject_public_key_info(encoded)
+ return _import_subjectPublicKeyInfo(sp_info)
+
+
+def _import_pkcs8(encoded, passphrase):
+ from Cryptodome.IO import PKCS8
+
+ k = PKCS8.unwrap(encoded, passphrase)
+ if k[0] != oid:
+ raise ValueError("No PKCS#8 encoded RSA key")
+ return _import_keyDER(k[1], passphrase)
+
+
+def _import_keyDER(extern_key, passphrase):
+ """Import an RSA key (public or private half), encoded in DER form."""
+
+ decodings = (_import_pkcs1_private,
+ _import_pkcs1_public,
+ _import_subjectPublicKeyInfo,
+ _import_x509_cert,
+ _import_pkcs8)
+
+ for decoding in decodings:
+ try:
+ return decoding(extern_key, passphrase)
+ except ValueError:
+ pass
+
+ raise ValueError("RSA key format is not supported")
+
+
+def _import_openssh_private_rsa(data, password):
+
+ from ._openssh import (import_openssh_private_generic,
+ read_bytes, read_string, check_padding)
+
+ ssh_name, decrypted = import_openssh_private_generic(data, password)
+
+ if ssh_name != "ssh-rsa":
+ raise ValueError("This SSH key is not RSA")
+
+ n, decrypted = read_bytes(decrypted)
+ e, decrypted = read_bytes(decrypted)
+ d, decrypted = read_bytes(decrypted)
+ iqmp, decrypted = read_bytes(decrypted)
+ p, decrypted = read_bytes(decrypted)
+ q, decrypted = read_bytes(decrypted)
+
+ _, padded = read_string(decrypted) # Comment
+ check_padding(padded)
+
+ build = [Integer.from_bytes(x) for x in (n, e, d, q, p, iqmp)]
+ return construct(build)
+
+
+def import_key(extern_key, passphrase=None):
+ """Import an RSA key (public or private).
+
+ Args:
+ extern_key (string or byte string):
+ The RSA key to import.
+
+ The following formats are supported for an RSA **public key**:
+
+ - X.509 certificate (binary or PEM format)
+ - X.509 ``subjectPublicKeyInfo`` DER SEQUENCE (binary or PEM
+ encoding)
+ - `PKCS#1`_ ``RSAPublicKey`` DER SEQUENCE (binary or PEM encoding)
+ - An OpenSSH line (e.g. the content of ``~/.ssh/id_ecdsa``, ASCII)
+
+ The following formats are supported for an RSA **private key**:
+
+ - PKCS#1 ``RSAPrivateKey`` DER SEQUENCE (binary or PEM encoding)
+ - `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo``
+ DER SEQUENCE (binary or PEM encoding)
+ - OpenSSH (text format, introduced in `OpenSSH 6.5`_)
+
+ For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.
+
+ passphrase (string or byte string):
+ For private keys only, the pass phrase that encrypts the key.
+
+ Returns: An RSA key object (:class:`RsaKey`).
+
+ Raises:
+ ValueError/IndexError/TypeError:
+ When the given key cannot be parsed (possibly because the pass
+ phrase is wrong).
+
+ .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
+ .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
+ .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt
+ .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
+ .. _`OpenSSH 6.5`: https://flak.tedunangst.com/post/new-openssh-key-format-and-bcrypt-pbkdf
+ """
+
+ from Cryptodome.IO import PEM
+
+ extern_key = tobytes(extern_key)
+ if passphrase is not None:
+ passphrase = tobytes(passphrase)
+
+ if extern_key.startswith(b'-----BEGIN OPENSSH PRIVATE KEY'):
+ text_encoded = tostr(extern_key)
+ openssh_encoded, marker, enc_flag = PEM.decode(text_encoded, passphrase)
+ result = _import_openssh_private_rsa(openssh_encoded, passphrase)
+ return result
+
+ if extern_key.startswith(b'-----'):
+ # This is probably a PEM encoded key.
+ (der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
+ if enc_flag:
+ passphrase = None
+ return _import_keyDER(der, passphrase)
+
+ if extern_key.startswith(b'ssh-rsa '):
+ # This is probably an OpenSSH key
+ keystring = binascii.a2b_base64(extern_key.split(b' ')[1])
+ keyparts = []
+ while len(keystring) > 4:
+ length = struct.unpack(">I", keystring[:4])[0]
+ keyparts.append(keystring[4:4 + length])
+ keystring = keystring[4 + length:]
+ e = Integer.from_bytes(keyparts[1])
+ n = Integer.from_bytes(keyparts[2])
+ return construct([n, e])
+
+ if len(extern_key) > 0 and bord(extern_key[0]) == 0x30:
+ # This is probably a DER encoded key
+ return _import_keyDER(extern_key, passphrase)
+
+ raise ValueError("RSA key format is not supported")
+
+
+# Backward compatibility
+importKey = import_key
+
+#: `Object ID`_ for the RSA encryption algorithm. This OID often indicates
+#: a generic RSA key, even when such key will be actually used for digital
+#: signatures.
+#:
+#: .. _`Object ID`: http://www.alvestrand.no/objectid/1.2.840.113549.1.1.1.html
+oid = "1.2.840.113549.1.1.1"
diff --git a/frozen_deps/Cryptodome/PublicKey/RSA.pyi b/frozen_deps/Cryptodome/PublicKey/RSA.pyi
new file mode 100644
index 0000000..e4d0369
--- /dev/null
+++ b/frozen_deps/Cryptodome/PublicKey/RSA.pyi
@@ -0,0 +1,50 @@
+from typing import Callable, Union, Tuple, Optional
+
+__all__ = ['generate', 'construct', 'import_key',
+ 'RsaKey', 'oid']
+
+RNG = Callable[[int], bytes]
+
+class RsaKey(object):
+ def __init__(self, **kwargs: int) -> None: ...
+ @property
+ def n(self) -> int: ...
+ @property
+ def e(self) -> int: ...
+ @property
+ def d(self) -> int: ...
+ @property
+ def p(self) -> int: ...
+ @property
+ def q(self) -> int: ...
+ @property
+ def u(self) -> int: ...
+ def size_in_bits(self) -> int: ...
+ def size_in_bytes(self) -> int: ...
+ def has_private(self) -> bool: ...
+ def can_encrypt(self) -> bool: ... # legacy
+ def can_sign(self) -> bool:... # legacy
+ def publickey(self) -> RsaKey: ...
+ def __eq__(self, other: object) -> bool: ...
+ def __ne__(self, other: object) -> bool: ...
+ def __getstate__(self) -> None: ...
+ def __repr__(self) -> str: ...
+ def __str__(self) -> str: ...
+ def export_key(self, format: Optional[str]="PEM", passphrase: Optional[str]=None, pkcs: Optional[int]=1,
+ protection: Optional[str]=None, randfunc: Optional[RNG]=None) -> bytes: ...
+
+ # Backward compatibility
+ exportKey = export_key
+
+def generate(bits: int, randfunc: Optional[RNG]=None, e: Optional[int]=65537) -> RsaKey: ...
+def construct(rsa_components: Union[Tuple[int, int], # n, e
+ Tuple[int, int, int], # n, e, d
+ Tuple[int, int, int, int, int], # n, e, d, p, q
+ Tuple[int, int, int, int, int, int]], # n, e, d, p, q, crt_q
+ consistency_check: Optional[bool]=True) -> RsaKey: ...
+def import_key(extern_key: Union[str, bytes], passphrase: Optional[str]=None) -> RsaKey: ...
+
+# Backward compatibility
+importKey = import_key
+
+oid: str
diff --git a/frozen_deps/Cryptodome/PublicKey/__init__.py b/frozen_deps/Cryptodome/PublicKey/__init__.py
new file mode 100644
index 0000000..4d019bf
--- /dev/null
+++ b/frozen_deps/Cryptodome/PublicKey/__init__.py
@@ -0,0 +1,95 @@
+# -*- 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.asn1 import (DerSequence, DerInteger, DerBitString,
+ DerObjectId, DerNull)
+
+
+def _expand_subject_public_key_info(encoded):
+ """Parse a SubjectPublicKeyInfo structure.
+
+ It returns a triple with:
+ * OID (string)
+ * encoded public key (bytes)
+ * Algorithm parameters (bytes or None)
+ """
+
+ #
+ # SubjectPublicKeyInfo ::= SEQUENCE {
+ # algorithm AlgorithmIdentifier,
+ # subjectPublicKey BIT STRING
+ # }
+ #
+ # AlgorithmIdentifier ::= SEQUENCE {
+ # algorithm OBJECT IDENTIFIER,
+ # parameters ANY DEFINED BY algorithm OPTIONAL
+ # }
+ #
+
+ spki = DerSequence().decode(encoded, nr_elements=2)
+ algo = DerSequence().decode(spki[0], nr_elements=(1,2))
+ algo_oid = DerObjectId().decode(algo[0])
+ spk = DerBitString().decode(spki[1]).value
+
+ if len(algo) == 1:
+ algo_params = None
+ else:
+ try:
+ DerNull().decode(algo[1])
+ algo_params = None
+ except:
+ algo_params = algo[1]
+
+ return algo_oid.value, spk, algo_params
+
+
+def _create_subject_public_key_info(algo_oid, secret_key, params=None):
+
+ if params is None:
+ params = DerNull()
+
+ spki = DerSequence([
+ DerSequence([
+ DerObjectId(algo_oid),
+ params]),
+ DerBitString(secret_key)
+ ])
+ return spki.encode()
+
+
+def _extract_subject_public_key_info(x509_certificate):
+ """Extract subjectPublicKeyInfo from a DER X.509 certificate."""
+
+ certificate = DerSequence().decode(x509_certificate, nr_elements=3)
+ tbs_certificate = DerSequence().decode(certificate[0],
+ nr_elements=range(6, 11))
+
+ index = 5
+ try:
+ tbs_certificate[0] + 1
+ # Version not present
+ version = 1
+ except TypeError:
+ version = DerInteger(explicit=0).decode(tbs_certificate[0]).value
+ if version not in (2, 3):
+ raise ValueError("Incorrect X.509 certificate version")
+ index = 6
+
+ return tbs_certificate[index]
diff --git a/frozen_deps/Cryptodome/PublicKey/__init__.pyi b/frozen_deps/Cryptodome/PublicKey/__init__.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/frozen_deps/Cryptodome/PublicKey/__init__.pyi
diff --git a/frozen_deps/Cryptodome/PublicKey/_ec_ws.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/PublicKey/_ec_ws.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..fba01e8
--- /dev/null
+++ b/frozen_deps/Cryptodome/PublicKey/_ec_ws.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/PublicKey/_openssh.py b/frozen_deps/Cryptodome/PublicKey/_openssh.py
new file mode 100644
index 0000000..53b16df
--- /dev/null
+++ b/frozen_deps/Cryptodome/PublicKey/_openssh.py
@@ -0,0 +1,135 @@
+# ===================================================================
+#
+# Copyright (c) 2019, Helder Eijs <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+import struct
+
+from Cryptodome.Cipher import AES
+from Cryptodome.Hash import SHA512
+from Cryptodome.Protocol.KDF import _bcrypt_hash
+from Cryptodome.Util.strxor import strxor
+from Cryptodome.Util.py3compat import tostr, bchr, bord
+
+
+def read_int4(data):
+ if len(data) < 4:
+ raise ValueError("Insufficient data")
+ value = struct.unpack(">I", data[:4])[0]
+ return value, data[4:]
+
+
+def read_bytes(data):
+ size, data = read_int4(data)
+ if len(data) < size:
+ raise ValueError("Insufficient data (V)")
+ return data[:size], data[size:]
+
+
+def read_string(data):
+ s, d = read_bytes(data)
+ return tostr(s), d
+
+
+def check_padding(pad):
+ for v, x in enumerate(pad):
+ if bord(x) != ((v + 1) & 0xFF):
+ raise ValueError("Incorrect padding")
+
+
+def import_openssh_private_generic(data, password):
+ # https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.key?annotate=HEAD
+ # https://github.com/openssh/openssh-portable/blob/master/sshkey.c
+ # https://coolaj86.com/articles/the-openssh-private-key-format/
+ # https://coolaj86.com/articles/the-ssh-public-key-format/
+
+ if not data.startswith(b'openssh-key-v1\x00'):
+ raise ValueError("Incorrect magic value")
+ data = data[15:]
+
+ ciphername, data = read_string(data)
+ kdfname, data = read_string(data)
+ kdfoptions, data = read_bytes(data)
+ number_of_keys, data = read_int4(data)
+
+ if number_of_keys != 1:
+ raise ValueError("We only handle 1 key at a time")
+
+ _, data = read_string(data) # Public key
+ encrypted, data = read_bytes(data)
+ if data:
+ raise ValueError("Too much data")
+
+ if len(encrypted) % 8 != 0:
+ raise ValueError("Incorrect payload length")
+
+ # Decrypt if necessary
+ if ciphername == 'none':
+ decrypted = encrypted
+ else:
+ if (ciphername, kdfname) != ('aes256-ctr', 'bcrypt'):
+ raise ValueError("Unsupported encryption scheme %s/%s" % (ciphername, kdfname))
+
+ salt, kdfoptions = read_bytes(kdfoptions)
+ iterations, kdfoptions = read_int4(kdfoptions)
+
+ if len(salt) != 16:
+ raise ValueError("Incorrect salt length")
+ if kdfoptions:
+ raise ValueError("Too much data in kdfoptions")
+
+ pwd_sha512 = SHA512.new(password).digest()
+ # We need 32+16 = 48 bytes, therefore 2 bcrypt outputs are sufficient
+ stripes = []
+ constant = b"OxychromaticBlowfishSwatDynamite"
+ for count in range(1, 3):
+ salt_sha512 = SHA512.new(salt + struct.pack(">I", count)).digest()
+ out_le = _bcrypt_hash(pwd_sha512, 6, salt_sha512, constant, False)
+ out = struct.pack("<IIIIIIII", *struct.unpack(">IIIIIIII", out_le))
+ acc = bytearray(out)
+ for _ in range(1, iterations):
+ out_le = _bcrypt_hash(pwd_sha512, 6, SHA512.new(out).digest(), constant, False)
+ out = struct.pack("<IIIIIIII", *struct.unpack(">IIIIIIII", out_le))
+ strxor(acc, out, output=acc)
+ stripes.append(acc[:24])
+
+ result = b"".join([bchr(a)+bchr(b) for (a, b) in zip(*stripes)])
+
+ cipher = AES.new(result[:32],
+ AES.MODE_CTR,
+ nonce=b"",
+ initial_value=result[32:32+16])
+ decrypted = cipher.decrypt(encrypted)
+
+ checkint1, decrypted = read_int4(decrypted)
+ checkint2, decrypted = read_int4(decrypted)
+ if checkint1 != checkint2:
+ raise ValueError("Incorrect checksum")
+ ssh_name, decrypted = read_string(decrypted)
+
+ return ssh_name, decrypted
diff --git a/frozen_deps/Cryptodome/PublicKey/_openssh.pyi b/frozen_deps/Cryptodome/PublicKey/_openssh.pyi
new file mode 100644
index 0000000..15f3677
--- /dev/null
+++ b/frozen_deps/Cryptodome/PublicKey/_openssh.pyi
@@ -0,0 +1,7 @@
+from typing import Tuple
+
+def read_int4(data: bytes) -> Tuple[int, bytes]: ...
+def read_bytes(data: bytes) -> Tuple[bytes, bytes]: ...
+def read_string(data: bytes) -> Tuple[str, bytes]: ...
+def check_padding(pad: bytes) -> None: ...
+def import_openssh_private_generic(data: bytes, password: bytes) -> Tuple[str, bytes]: ...
diff --git a/frozen_deps/Cryptodome/Random/__init__.py b/frozen_deps/Cryptodome/Random/__init__.py
new file mode 100644
index 0000000..fd18d86
--- /dev/null
+++ b/frozen_deps/Cryptodome/Random/__init__.py
@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*-
+#
+# Random/__init__.py : PyCryptodome random number generation
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+__all__ = ['new', 'get_random_bytes']
+
+from os import urandom
+
+class _UrandomRNG(object):
+
+ def read(self, n):
+ """Return a random byte string of the desired size."""
+ return urandom(n)
+
+ def flush(self):
+ """Method provided for backward compatibility only."""
+ pass
+
+ def reinit(self):
+ """Method provided for backward compatibility only."""
+ pass
+
+ def close(self):
+ """Method provided for backward compatibility only."""
+ pass
+
+
+def new(*args, **kwargs):
+ """Return a file-like object that outputs cryptographically random bytes."""
+ return _UrandomRNG()
+
+
+def atfork():
+ pass
+
+
+#: Function that returns a random byte string of the desired size.
+get_random_bytes = urandom
+
diff --git a/frozen_deps/Cryptodome/Random/__init__.pyi b/frozen_deps/Cryptodome/Random/__init__.pyi
new file mode 100644
index 0000000..ddc5b9b
--- /dev/null
+++ b/frozen_deps/Cryptodome/Random/__init__.pyi
@@ -0,0 +1,19 @@
+from typing import Any
+
+__all__ = ['new', 'get_random_bytes']
+
+from os import urandom
+
+class _UrandomRNG(object):
+
+ def read(self, n: int) -> bytes:...
+ def flush(self) -> None: ...
+ def reinit(self) -> None: ...
+ def close(self) -> None: ...
+
+def new(*args: Any, **kwargs: Any) -> _UrandomRNG: ...
+
+def atfork() -> None: ...
+
+get_random_bytes = urandom
+
diff --git a/frozen_deps/Cryptodome/Random/random.py b/frozen_deps/Cryptodome/Random/random.py
new file mode 100644
index 0000000..da30795
--- /dev/null
+++ b/frozen_deps/Cryptodome/Random/random.py
@@ -0,0 +1,138 @@
+# -*- coding: utf-8 -*-
+#
+# Random/random.py : Strong alternative for the standard 'random' module
+#
+# Written in 2008 by Dwayne C. Litzenberger <[email protected]>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+__all__ = ['StrongRandom', 'getrandbits', 'randrange', 'randint', 'choice', 'shuffle', 'sample']
+
+from Cryptodome import Random
+
+from Cryptodome.Util.py3compat import is_native_int
+
+class StrongRandom(object):
+ def __init__(self, rng=None, randfunc=None):
+ if randfunc is None and rng is None:
+ self._randfunc = None
+ elif randfunc is not None and rng is None:
+ self._randfunc = randfunc
+ elif randfunc is None and rng is not None:
+ self._randfunc = rng.read
+ else:
+ raise ValueError("Cannot specify both 'rng' and 'randfunc'")
+
+ def getrandbits(self, k):
+ """Return an integer with k random bits."""
+
+ if self._randfunc is None:
+ self._randfunc = Random.new().read
+ mask = (1 << k) - 1
+ return mask & bytes_to_long(self._randfunc(ceil_div(k, 8)))
+
+ def randrange(self, *args):
+ """randrange([start,] stop[, step]):
+ Return a randomly-selected element from range(start, stop, step)."""
+ if len(args) == 3:
+ (start, stop, step) = args
+ elif len(args) == 2:
+ (start, stop) = args
+ step = 1
+ elif len(args) == 1:
+ (stop,) = args
+ start = 0
+ step = 1
+ else:
+ raise TypeError("randrange expected at most 3 arguments, got %d" % (len(args),))
+ if (not is_native_int(start) or not is_native_int(stop) or not
+ is_native_int(step)):
+ raise TypeError("randrange requires integer arguments")
+ if step == 0:
+ raise ValueError("randrange step argument must not be zero")
+
+ num_choices = ceil_div(stop - start, step)
+ if num_choices < 0:
+ num_choices = 0
+ if num_choices < 1:
+ raise ValueError("empty range for randrange(%r, %r, %r)" % (start, stop, step))
+
+ # Pick a random number in the range of possible numbers
+ r = num_choices
+ while r >= num_choices:
+ r = self.getrandbits(size(num_choices))
+
+ return start + (step * r)
+
+ def randint(self, a, b):
+ """Return a random integer N such that a <= N <= b."""
+ if not is_native_int(a) or not is_native_int(b):
+ raise TypeError("randint requires integer arguments")
+ N = self.randrange(a, b+1)
+ assert a <= N <= b
+ return N
+
+ def choice(self, seq):
+ """Return a random element from a (non-empty) sequence.
+
+ If the seqence is empty, raises IndexError.
+ """
+ if len(seq) == 0:
+ raise IndexError("empty sequence")
+ return seq[self.randrange(len(seq))]
+
+ def shuffle(self, x):
+ """Shuffle the sequence in place."""
+ # Fisher-Yates shuffle. O(n)
+ # See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
+ # Working backwards from the end of the array, we choose a random item
+ # from the remaining items until all items have been chosen.
+ for i in range(len(x)-1, 0, -1): # iterate from len(x)-1 downto 1
+ j = self.randrange(0, i+1) # choose random j such that 0 <= j <= i
+ x[i], x[j] = x[j], x[i] # exchange x[i] and x[j]
+
+ def sample(self, population, k):
+ """Return a k-length list of unique elements chosen from the population sequence."""
+
+ num_choices = len(population)
+ if k > num_choices:
+ raise ValueError("sample larger than population")
+
+ retval = []
+ selected = {} # we emulate a set using a dict here
+ for i in range(k):
+ r = None
+ while r is None or r in selected:
+ r = self.randrange(num_choices)
+ retval.append(population[r])
+ selected[r] = 1
+ return retval
+
+_r = StrongRandom()
+getrandbits = _r.getrandbits
+randrange = _r.randrange
+randint = _r.randint
+choice = _r.choice
+shuffle = _r.shuffle
+sample = _r.sample
+
+# These are at the bottom to avoid problems with recursive imports
+from Cryptodome.Util.number import ceil_div, bytes_to_long, long_to_bytes, size
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/frozen_deps/Cryptodome/Random/random.pyi b/frozen_deps/Cryptodome/Random/random.pyi
new file mode 100644
index 0000000..f873c4a
--- /dev/null
+++ b/frozen_deps/Cryptodome/Random/random.pyi
@@ -0,0 +1,20 @@
+from typing import Callable, Tuple, Union, Sequence, Any, Optional
+
+__all__ = ['StrongRandom', 'getrandbits', 'randrange', 'randint', 'choice', 'shuffle', 'sample']
+
+class StrongRandom(object):
+ def __init__(self, rng: Optional[Any]=None, randfunc: Optional[Callable]=None) -> None: ... # TODO What is rng?
+ def getrandbits(self, k: int) -> int: ...
+ def randrange(self, start: int, stop: int = ..., step: int = ...) -> int: ...
+ def randint(self, a: int, b: int) -> int: ...
+ def choice(self, seq: Sequence) -> object: ...
+ def shuffle(self, x: Sequence) -> None: ...
+ def sample(self, population: Sequence, k: int) -> list: ...
+
+_r = StrongRandom()
+getrandbits = _r.getrandbits
+randrange = _r.randrange
+randint = _r.randint
+choice = _r.choice
+shuffle = _r.shuffle
+sample = _r.sample
diff --git a/frozen_deps/Cryptodome/Signature/DSS.py b/frozen_deps/Cryptodome/Signature/DSS.py
new file mode 100644
index 0000000..3dcbeb4
--- /dev/null
+++ b/frozen_deps/Cryptodome/Signature/DSS.py
@@ -0,0 +1,413 @@
+#
+# Signature/DSS.py : DSS.py
+#
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+__all__ = ['new']
+
+
+from Cryptodome.Util.asn1 import DerSequence
+from Cryptodome.Util.number import long_to_bytes
+from Cryptodome.Math.Numbers import Integer
+
+from Cryptodome.Hash import HMAC
+from Cryptodome.PublicKey.ECC import EccKey
+
+
+class DssSigScheme(object):
+ """A (EC)DSA signature object.
+ Do not instantiate directly.
+ Use :func:`Cryptodome.Signature.DSS.new`.
+ """
+
+ def __init__(self, key, encoding, order):
+ """Create a new Digital Signature Standard (DSS) object.
+
+ Do not instantiate this object directly,
+ use `Cryptodome.Signature.DSS.new` instead.
+ """
+
+ self._key = key
+ self._encoding = encoding
+ self._order = order
+
+ self._order_bits = self._order.size_in_bits()
+ self._order_bytes = (self._order_bits - 1) // 8 + 1
+
+ def can_sign(self):
+ """Return ``True`` if this signature object can be used
+ for signing messages."""
+
+ return self._key.has_private()
+
+ def _compute_nonce(self, msg_hash):
+ raise NotImplementedError("To be provided by subclasses")
+
+ def _valid_hash(self, msg_hash):
+ raise NotImplementedError("To be provided by subclasses")
+
+ def sign(self, msg_hash):
+ """Produce the DSA/ECDSA signature of a message.
+
+ :parameter msg_hash:
+ The hash that was carried out over the message.
+ The object belongs to the :mod:`Cryptodome.Hash` package.
+
+ Under mode *'fips-186-3'*, the hash must be a FIPS
+ approved secure hash (SHA-1 or a member of the SHA-2 family),
+ of cryptographic strength appropriate for the DSA key.
+ For instance, a 3072/256 DSA key can only be used
+ in combination with SHA-512.
+ :type msg_hash: hash object
+
+ :return: The signature as a *byte string*
+ :raise ValueError: if the hash algorithm is incompatible to the (EC)DSA key
+ :raise TypeError: if the (EC)DSA key has no private half
+ """
+
+ if not self._valid_hash(msg_hash):
+ raise ValueError("Hash is not sufficiently strong")
+
+ # Generate the nonce k (critical!)
+ nonce = self._compute_nonce(msg_hash)
+
+ # Perform signature using the raw API
+ z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes])
+ sig_pair = self._key._sign(z, nonce)
+
+ # Encode the signature into a single byte string
+ if self._encoding == 'binary':
+ output = b"".join([long_to_bytes(x, self._order_bytes)
+ for x in sig_pair])
+ else:
+ # Dss-sig ::= SEQUENCE {
+ # r INTEGER,
+ # s INTEGER
+ # }
+ # Ecdsa-Sig-Value ::= SEQUENCE {
+ # r INTEGER,
+ # s INTEGER
+ # }
+ output = DerSequence(sig_pair).encode()
+
+ return output
+
+ def verify(self, msg_hash, signature):
+ """Check if a certain (EC)DSA signature is authentic.
+
+ :parameter msg_hash:
+ The hash that was carried out over the message.
+ This is an object belonging to the :mod:`Cryptodome.Hash` module.
+
+ Under mode *'fips-186-3'*, the hash must be a FIPS
+ approved secure hash (SHA-1 or a member of the SHA-2 family),
+ of cryptographic strength appropriate for the DSA key.
+ For instance, a 3072/256 DSA key can only be used in
+ combination with SHA-512.
+ :type msg_hash: hash object
+
+ :parameter signature:
+ The signature that needs to be validated
+ :type signature: byte string
+
+ :raise ValueError: if the signature is not authentic
+ """
+
+ if not self._valid_hash(msg_hash):
+ raise ValueError("Hash is not sufficiently strong")
+
+ if self._encoding == 'binary':
+ if len(signature) != (2 * self._order_bytes):
+ raise ValueError("The signature is not authentic (length)")
+ r_prime, s_prime = [Integer.from_bytes(x)
+ for x in (signature[:self._order_bytes],
+ signature[self._order_bytes:])]
+ else:
+ try:
+ der_seq = DerSequence().decode(signature, strict=True)
+ except (ValueError, IndexError):
+ raise ValueError("The signature is not authentic (DER)")
+ if len(der_seq) != 2 or not der_seq.hasOnlyInts():
+ raise ValueError("The signature is not authentic (DER content)")
+ r_prime, s_prime = Integer(der_seq[0]), Integer(der_seq[1])
+
+ if not (0 < r_prime < self._order) or not (0 < s_prime < self._order):
+ raise ValueError("The signature is not authentic (d)")
+
+ z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes])
+ result = self._key._verify(z, (r_prime, s_prime))
+ if not result:
+ raise ValueError("The signature is not authentic")
+ # Make PyCryptodome code to fail
+ return False
+
+
+class DeterministicDsaSigScheme(DssSigScheme):
+ # Also applicable to ECDSA
+
+ def __init__(self, key, encoding, order, private_key):
+ super(DeterministicDsaSigScheme, self).__init__(key, encoding, order)
+ self._private_key = private_key
+
+ def _bits2int(self, bstr):
+ """See 2.3.2 in RFC6979"""
+
+ result = Integer.from_bytes(bstr)
+ q_len = self._order.size_in_bits()
+ b_len = len(bstr) * 8
+ if b_len > q_len:
+ # Only keep leftmost q_len bits
+ result >>= (b_len - q_len)
+ return result
+
+ def _int2octets(self, int_mod_q):
+ """See 2.3.3 in RFC6979"""
+
+ assert 0 < int_mod_q < self._order
+ return long_to_bytes(int_mod_q, self._order_bytes)
+
+ def _bits2octets(self, bstr):
+ """See 2.3.4 in RFC6979"""
+
+ z1 = self._bits2int(bstr)
+ if z1 < self._order:
+ z2 = z1
+ else:
+ z2 = z1 - self._order
+ return self._int2octets(z2)
+
+ def _compute_nonce(self, mhash):
+ """Generate k in a deterministic way"""
+
+ # See section 3.2 in RFC6979.txt
+ # Step a
+ h1 = mhash.digest()
+ # Step b
+ mask_v = b'\x01' * mhash.digest_size
+ # Step c
+ nonce_k = b'\x00' * mhash.digest_size
+
+ for int_oct in (b'\x00', b'\x01'):
+ # Step d/f
+ nonce_k = HMAC.new(nonce_k,
+ mask_v + int_oct +
+ self._int2octets(self._private_key) +
+ self._bits2octets(h1), mhash).digest()
+ # Step e/g
+ mask_v = HMAC.new(nonce_k, mask_v, mhash).digest()
+
+ nonce = -1
+ while not (0 < nonce < self._order):
+ # Step h.C (second part)
+ if nonce != -1:
+ nonce_k = HMAC.new(nonce_k, mask_v + b'\x00',
+ mhash).digest()
+ mask_v = HMAC.new(nonce_k, mask_v, mhash).digest()
+
+ # Step h.A
+ mask_t = b""
+
+ # Step h.B
+ while len(mask_t) < self._order_bytes:
+ mask_v = HMAC.new(nonce_k, mask_v, mhash).digest()
+ mask_t += mask_v
+
+ # Step h.C (first part)
+ nonce = self._bits2int(mask_t)
+ return nonce
+
+ def _valid_hash(self, msg_hash):
+ return True
+
+
+class FipsDsaSigScheme(DssSigScheme):
+
+ #: List of L (bit length of p) and N (bit length of q) combinations
+ #: that are allowed by FIPS 186-3. The security level is provided in
+ #: Table 2 of FIPS 800-57 (rev3).
+ _fips_186_3_L_N = (
+ (1024, 160), # 80 bits (SHA-1 or stronger)
+ (2048, 224), # 112 bits (SHA-224 or stronger)
+ (2048, 256), # 128 bits (SHA-256 or stronger)
+ (3072, 256) # 256 bits (SHA-512)
+ )
+
+ def __init__(self, key, encoding, order, randfunc):
+ super(FipsDsaSigScheme, self).__init__(key, encoding, order)
+ self._randfunc = randfunc
+
+ L = Integer(key.p).size_in_bits()
+ if (L, self._order_bits) not in self._fips_186_3_L_N:
+ error = ("L/N (%d, %d) is not compliant to FIPS 186-3"
+ % (L, self._order_bits))
+ raise ValueError(error)
+
+ def _compute_nonce(self, msg_hash):
+ # hash is not used
+ return Integer.random_range(min_inclusive=1,
+ max_exclusive=self._order,
+ randfunc=self._randfunc)
+
+ def _valid_hash(self, msg_hash):
+ """Verify that SHA-1, SHA-2 or SHA-3 are used"""
+ return (msg_hash.oid == "1.3.14.3.2.26" or
+ msg_hash.oid.startswith("2.16.840.1.101.3.4.2."))
+
+
+class FipsEcDsaSigScheme(DssSigScheme):
+
+ def __init__(self, key, encoding, order, randfunc):
+ super(FipsEcDsaSigScheme, self).__init__(key, encoding, order)
+ self._randfunc = randfunc
+
+ def _compute_nonce(self, msg_hash):
+ return Integer.random_range(min_inclusive=1,
+ max_exclusive=self._key._curve.order,
+ randfunc=self._randfunc)
+
+ def _valid_hash(self, msg_hash):
+ """Verify that SHA-[23] (256|384|512) bits are used to
+ match the security of P-256 (128 bits), P-384 (192 bits)
+ or P-521 (256 bits)"""
+
+ modulus_bits = self._key.pointQ.size_in_bits()
+
+ sha256 = ( "2.16.840.1.101.3.4.2.1", "2.16.840.1.101.3.4.2.8" )
+ sha384 = ( "2.16.840.1.101.3.4.2.2", "2.16.840.1.101.3.4.2.9" )
+ sha512 = ( "2.16.840.1.101.3.4.2.3", "2.16.840.1.101.3.4.2.10")
+
+ if msg_hash.oid in sha256:
+ return modulus_bits <= 256
+ elif msg_hash.oid in sha384:
+ return modulus_bits <= 384
+ else:
+ return msg_hash.oid in sha512
+
+
+def new(key, mode, encoding='binary', randfunc=None):
+ """Create a signature object :class:`DSS_SigScheme` that
+ can perform (EC)DSA signature or verification.
+
+ .. note::
+ Refer to `NIST SP 800 Part 1 Rev 4`_ (or newer release) for an
+ overview of the recommended key lengths.
+
+ :parameter key:
+ The key to use for computing the signature (*private* keys only)
+ or verifying one: it must be either
+ :class:`Cryptodome.PublicKey.DSA` or :class:`Cryptodome.PublicKey.ECC`.
+
+ For DSA keys, let ``L`` and ``N`` be the bit lengths of the modulus ``p``
+ and of ``q``: the pair ``(L,N)`` must appear in the following list,
+ in compliance to section 4.2 of `FIPS 186-4`_:
+
+ - (1024, 160) *legacy only; do not create new signatures with this*
+ - (2048, 224) *deprecated; do not create new signatures with this*
+ - (2048, 256)
+ - (3072, 256)
+
+ For ECC, only keys over P-256, P384, and P-521 are accepted.
+ :type key:
+ a key object
+
+ :parameter mode:
+ The parameter can take these values:
+
+ - *'fips-186-3'*. The signature generation is randomized and carried out
+ according to `FIPS 186-3`_: the nonce ``k`` is taken from the RNG.
+ - *'deterministic-rfc6979'*. The signature generation is not
+ randomized. See RFC6979_.
+ :type mode:
+ string
+
+ :parameter encoding:
+ How the signature is encoded. This value determines the output of
+ :meth:`sign` and the input to :meth:`verify`.
+
+ The following values are accepted:
+
+ - *'binary'* (default), the signature is the raw concatenation
+ of ``r`` and ``s``. It is defined in the IEEE P.1363 standard.
+
+ For DSA, the size in bytes of the signature is ``N/4`` bytes
+ (e.g. 64 for ``N=256``).
+
+ For ECDSA, the signature is always twice the length of a point
+ coordinate (e.g. 64 bytes for P-256).
+
+ - *'der'*, the signature is a ASN.1 DER SEQUENCE
+ with two INTEGERs (``r`` and ``s``). It is defined in RFC3279_.
+ The size of the signature is variable.
+ :type encoding: string
+
+ :parameter randfunc:
+ A function that returns random *byte strings*, of a given length.
+ If omitted, the internal RNG is used.
+ Only applicable for the *'fips-186-3'* mode.
+ :type randfunc: callable
+
+ .. _FIPS 186-3: http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf
+ .. _FIPS 186-4: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
+ .. _NIST SP 800 Part 1 Rev 4: http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r4.pdf
+ .. _RFC6979: http://tools.ietf.org/html/rfc6979
+ .. _RFC3279: https://tools.ietf.org/html/rfc3279#section-2.2.2
+ """
+
+ # The goal of the 'mode' parameter is to avoid to
+ # have the current version of the standard as default.
+ #
+ # Over time, such version will be superseded by (for instance)
+ # FIPS 186-4 and it will be odd to have -3 as default.
+
+ if encoding not in ('binary', 'der'):
+ raise ValueError("Unknown encoding '%s'" % encoding)
+
+ if isinstance(key, EccKey):
+ order = key._curve.order
+ private_key_attr = 'd'
+ else:
+ order = Integer(key.q)
+ private_key_attr = 'x'
+
+ if key.has_private():
+ private_key = getattr(key, private_key_attr)
+ else:
+ private_key = None
+
+ if mode == 'deterministic-rfc6979':
+ return DeterministicDsaSigScheme(key, encoding, order, private_key)
+ elif mode == 'fips-186-3':
+ if isinstance(key, EccKey):
+ return FipsEcDsaSigScheme(key, encoding, order, randfunc)
+ else:
+ return FipsDsaSigScheme(key, encoding, order, randfunc)
+ else:
+ raise ValueError("Unknown DSS mode '%s'" % mode)
diff --git a/frozen_deps/Cryptodome/Signature/DSS.pyi b/frozen_deps/Cryptodome/Signature/DSS.pyi
new file mode 100644
index 0000000..52ecc8f
--- /dev/null
+++ b/frozen_deps/Cryptodome/Signature/DSS.pyi
@@ -0,0 +1,27 @@
+from typing import Union, Optional, Callable
+from typing_extensions import Protocol
+
+from Cryptodome.PublicKey.DSA import DsaKey
+from Cryptodome.PublicKey.ECC import EccKey
+
+class Hash(Protocol):
+ def digest(self) -> bytes: ...
+
+__all__ = ['new']
+
+class DssSigScheme:
+ def __init__(self, key: Union[DsaKey, EccKey], encoding: str, order: int) -> None: ...
+ def can_sign(self) -> bool: ...
+ def sign(self, msg_hash: Hash) -> bytes: ...
+ def verify(self, msg_hash: Hash, signature: bytes) -> bool: ...
+
+class DeterministicDsaSigScheme(DssSigScheme):
+ def __init__(self, key, encoding, order, private_key) -> None: ...
+
+class FipsDsaSigScheme(DssSigScheme):
+ def __init__(self, key: DsaKey, encoding: str, order: int, randfunc: Callable) -> None: ...
+
+class FipsEcDsaSigScheme(DssSigScheme):
+ def __init__(self, key: EccKey, encoding: str, order: int, randfunc: Callable) -> None: ...
+
+def new(key: Union[DsaKey, EccKey], mode: str, encoding: Optional[str]='binary', randfunc: Optional[Callable]=None) -> Union[DeterministicDsaSigScheme, FipsDsaSigScheme, FipsEcDsaSigScheme]: ...
diff --git a/frozen_deps/Cryptodome/Signature/PKCS1_PSS.py b/frozen_deps/Cryptodome/Signature/PKCS1_PSS.py
new file mode 100644
index 0000000..1e7e5b5
--- /dev/null
+++ b/frozen_deps/Cryptodome/Signature/PKCS1_PSS.py
@@ -0,0 +1,55 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+"""
+Legacy module for PKCS#1 PSS signatures.
+
+:undocumented: __package__
+"""
+
+import types
+
+from Cryptodome.Signature import pss
+
+
+def _pycrypto_verify(self, hash_object, signature):
+ try:
+ self._verify(hash_object, signature)
+ except (ValueError, TypeError):
+ return False
+ return True
+
+
+def new(rsa_key, mgfunc=None, saltLen=None, randfunc=None):
+ pkcs1 = pss.new(rsa_key, mask_func=mgfunc,
+ salt_bytes=saltLen, rand_func=randfunc)
+ pkcs1._verify = pkcs1.verify
+ pkcs1.verify = types.MethodType(_pycrypto_verify, pkcs1)
+ return pkcs1
diff --git a/frozen_deps/Cryptodome/Signature/PKCS1_PSS.pyi b/frozen_deps/Cryptodome/Signature/PKCS1_PSS.pyi
new file mode 100644
index 0000000..7ed68e6
--- /dev/null
+++ b/frozen_deps/Cryptodome/Signature/PKCS1_PSS.pyi
@@ -0,0 +1,7 @@
+from typing import Optional, Callable
+
+from Cryptodome.PublicKey.RSA import RsaKey
+from Cryptodome.Signature.pss import PSS_SigScheme
+
+
+def new(rsa_key: RsaKey, mgfunc: Optional[Callable]=None, saltLen: Optional[int]=None, randfunc: Optional[Callable]=None) -> PSS_SigScheme: ...
diff --git a/frozen_deps/Cryptodome/Signature/PKCS1_v1_5.py b/frozen_deps/Cryptodome/Signature/PKCS1_v1_5.py
new file mode 100644
index 0000000..d560663
--- /dev/null
+++ b/frozen_deps/Cryptodome/Signature/PKCS1_v1_5.py
@@ -0,0 +1,53 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+"""
+Legacy module for PKCS#1 v1.5 signatures.
+
+:undocumented: __package__
+"""
+
+import types
+
+from Cryptodome.Signature import pkcs1_15
+
+def _pycrypto_verify(self, hash_object, signature):
+ try:
+ self._verify(hash_object, signature)
+ except (ValueError, TypeError):
+ return False
+ return True
+
+def new(rsa_key):
+ pkcs1 = pkcs1_15.new(rsa_key)
+ pkcs1._verify = pkcs1.verify
+ pkcs1.verify = types.MethodType(_pycrypto_verify, pkcs1)
+ return pkcs1
+
diff --git a/frozen_deps/Cryptodome/Signature/PKCS1_v1_5.pyi b/frozen_deps/Cryptodome/Signature/PKCS1_v1_5.pyi
new file mode 100644
index 0000000..5851e5b
--- /dev/null
+++ b/frozen_deps/Cryptodome/Signature/PKCS1_v1_5.pyi
@@ -0,0 +1,6 @@
+from Cryptodome.PublicKey.RSA import RsaKey
+
+from Cryptodome.Signature.pkcs1_15 import PKCS115_SigScheme
+
+
+def new(rsa_key: RsaKey) -> PKCS115_SigScheme: ... \ No newline at end of file
diff --git a/frozen_deps/Cryptodome/Signature/__init__.py b/frozen_deps/Cryptodome/Signature/__init__.py
new file mode 100644
index 0000000..da028a5
--- /dev/null
+++ b/frozen_deps/Cryptodome/Signature/__init__.py
@@ -0,0 +1,36 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+"""Digital signature protocols
+
+A collection of standardized protocols to carry out digital signatures.
+"""
+
+__all__ = ['PKCS1_v1_5', 'PKCS1_PSS', 'DSS', 'pkcs1_15', 'pss']
diff --git a/frozen_deps/Cryptodome/Signature/pkcs1_15.py b/frozen_deps/Cryptodome/Signature/pkcs1_15.py
new file mode 100644
index 0000000..f572f85
--- /dev/null
+++ b/frozen_deps/Cryptodome/Signature/pkcs1_15.py
@@ -0,0 +1,222 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# 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 Cryptodome.Util.number
+from Cryptodome.Util.number import ceil_div, bytes_to_long, long_to_bytes
+from Cryptodome.Util.asn1 import DerSequence, DerNull, DerOctetString, DerObjectId
+
+class PKCS115_SigScheme:
+ """A signature object for ``RSASSA-PKCS1-v1_5``.
+ Do not instantiate directly.
+ Use :func:`Cryptodome.Signature.pkcs1_15.new`.
+ """
+
+ def __init__(self, rsa_key):
+ """Initialize this PKCS#1 v1.5 signature scheme object.
+
+ :Parameters:
+ rsa_key : an RSA key object
+ Creation of signatures is only possible if this is a *private*
+ RSA key. Verification of signatures is always possible.
+ """
+ self._key = rsa_key
+
+ def can_sign(self):
+ """Return ``True`` if this object can be used to sign messages."""
+ return self._key.has_private()
+
+ def sign(self, msg_hash):
+ """Create the PKCS#1 v1.5 signature of a message.
+
+ This function is also called ``RSASSA-PKCS1-V1_5-SIGN`` and
+ it is specified in
+ `section 8.2.1 of RFC8017 <https://tools.ietf.org/html/rfc8017#page-36>`_.
+
+ :parameter msg_hash:
+ This is an object from the :mod:`Cryptodome.Hash` package.
+ It has been used to digest the message to sign.
+ :type msg_hash: hash object
+
+ :return: the signature encoded as a *byte string*.
+ :raise ValueError: if the RSA key is not long enough for the given hash algorithm.
+ :raise TypeError: if the RSA key has no private half.
+ """
+
+ # See 8.2.1 in RFC3447
+ modBits = Cryptodome.Util.number.size(self._key.n)
+ k = ceil_div(modBits,8) # Convert from bits to bytes
+
+ # Step 1
+ em = _EMSA_PKCS1_V1_5_ENCODE(msg_hash, k)
+ # Step 2a (OS2IP)
+ em_int = bytes_to_long(em)
+ # Step 2b (RSASP1)
+ m_int = self._key._decrypt(em_int)
+ # Step 2c (I2OSP)
+ signature = long_to_bytes(m_int, k)
+ return signature
+
+ def verify(self, msg_hash, signature):
+ """Check if the PKCS#1 v1.5 signature over a message is valid.
+
+ This function is also called ``RSASSA-PKCS1-V1_5-VERIFY`` and
+ it is specified in
+ `section 8.2.2 of RFC8037 <https://tools.ietf.org/html/rfc8017#page-37>`_.
+
+ :parameter msg_hash:
+ The hash that was carried out over the message. This is an object
+ belonging to the :mod:`Cryptodome.Hash` module.
+ :type parameter: hash object
+
+ :parameter signature:
+ The signature that needs to be validated.
+ :type signature: byte string
+
+ :raise ValueError: if the signature is not valid.
+ """
+
+ # See 8.2.2 in RFC3447
+ modBits = Cryptodome.Util.number.size(self._key.n)
+ k = ceil_div(modBits, 8) # Convert from bits to bytes
+
+ # Step 1
+ if len(signature) != k:
+ raise ValueError("Invalid signature")
+ # Step 2a (O2SIP)
+ signature_int = bytes_to_long(signature)
+ # Step 2b (RSAVP1)
+ em_int = self._key._encrypt(signature_int)
+ # Step 2c (I2OSP)
+ em1 = long_to_bytes(em_int, k)
+ # Step 3
+ try:
+ possible_em1 = [ _EMSA_PKCS1_V1_5_ENCODE(msg_hash, k, True) ]
+ # MD2/4/5 hashes always require NULL params in AlgorithmIdentifier.
+ # For all others, it is optional.
+ try:
+ algorithm_is_md = msg_hash.oid.startswith('1.2.840.113549.2.')
+ except AttributeError:
+ algorithm_is_md = False
+ if not algorithm_is_md: # MD2/MD4/MD5
+ possible_em1.append(_EMSA_PKCS1_V1_5_ENCODE(msg_hash, k, False))
+ except ValueError:
+ raise ValueError("Invalid signature")
+ # Step 4
+ # By comparing the full encodings (as opposed to checking each
+ # of its components one at a time) we avoid attacks to the padding
+ # scheme like Bleichenbacher's (see http://www.mail-archive.com/[email protected]/msg06537).
+ #
+ if em1 not in possible_em1:
+ raise ValueError("Invalid signature")
+ pass
+
+
+def _EMSA_PKCS1_V1_5_ENCODE(msg_hash, emLen, with_hash_parameters=True):
+ """
+ Implement the ``EMSA-PKCS1-V1_5-ENCODE`` function, as defined
+ in PKCS#1 v2.1 (RFC3447, 9.2).
+
+ ``_EMSA-PKCS1-V1_5-ENCODE`` actually accepts the message ``M`` as input,
+ and hash it internally. Here, we expect that the message has already
+ been hashed instead.
+
+ :Parameters:
+ msg_hash : hash object
+ The hash object that holds the digest of the message being signed.
+ emLen : int
+ The length the final encoding must have, in bytes.
+ with_hash_parameters : bool
+ If True (default), include NULL parameters for the hash
+ algorithm in the ``digestAlgorithm`` SEQUENCE.
+
+ :attention: the early standard (RFC2313) stated that ``DigestInfo``
+ had to be BER-encoded. This means that old signatures
+ might have length tags in indefinite form, which
+ is not supported in DER. Such encoding cannot be
+ reproduced by this function.
+
+ :Return: An ``emLen`` byte long string that encodes the hash.
+ """
+
+ # First, build the ASN.1 DER object DigestInfo:
+ #
+ # DigestInfo ::= SEQUENCE {
+ # digestAlgorithm AlgorithmIdentifier,
+ # digest OCTET STRING
+ # }
+ #
+ # where digestAlgorithm identifies the hash function and shall be an
+ # algorithm ID with an OID in the set PKCS1-v1-5DigestAlgorithms.
+ #
+ # PKCS1-v1-5DigestAlgorithms ALGORITHM-IDENTIFIER ::= {
+ # { OID id-md2 PARAMETERS NULL }|
+ # { OID id-md5 PARAMETERS NULL }|
+ # { OID id-sha1 PARAMETERS NULL }|
+ # { OID id-sha256 PARAMETERS NULL }|
+ # { OID id-sha384 PARAMETERS NULL }|
+ # { OID id-sha512 PARAMETERS NULL }
+ # }
+ #
+ # Appendix B.1 also says that for SHA-1/-2 algorithms, the parameters
+ # should be omitted. They may be present, but when they are, they shall
+ # have NULL value.
+
+ digestAlgo = DerSequence([ DerObjectId(msg_hash.oid).encode() ])
+
+ if with_hash_parameters:
+ digestAlgo.append(DerNull().encode())
+
+ digest = DerOctetString(msg_hash.digest())
+ digestInfo = DerSequence([
+ digestAlgo.encode(),
+ digest.encode()
+ ]).encode()
+
+ # We need at least 11 bytes for the remaining data: 3 fixed bytes and
+ # at least 8 bytes of padding).
+ if emLen<len(digestInfo)+11:
+ raise TypeError("Selected hash algorith has a too long digest (%d bytes)." % len(digest))
+ PS = b'\xFF' * (emLen - len(digestInfo) - 3)
+ return b'\x00\x01' + PS + b'\x00' + digestInfo
+
+def new(rsa_key):
+ """Create a signature object for creating
+ or verifying PKCS#1 v1.5 signatures.
+
+ :parameter rsa_key:
+ The RSA key to use for signing or verifying the message.
+ This is a :class:`Cryptodome.PublicKey.RSA` object.
+ Signing is only possible when ``rsa_key`` is a **private** RSA key.
+ :type rsa_key: RSA object
+
+ :return: a :class:`PKCS115_SigScheme` signature object
+ """
+ return PKCS115_SigScheme(rsa_key)
+
diff --git a/frozen_deps/Cryptodome/Signature/pkcs1_15.pyi b/frozen_deps/Cryptodome/Signature/pkcs1_15.pyi
new file mode 100644
index 0000000..04faf60
--- /dev/null
+++ b/frozen_deps/Cryptodome/Signature/pkcs1_15.pyi
@@ -0,0 +1,17 @@
+from typing import Optional
+from typing_extensions import Protocol
+
+from Cryptodome.PublicKey.RSA import RsaKey
+
+class Hash(Protocol):
+ def digest(self) -> bytes: ...
+
+class PKCS115_SigScheme:
+ def __init__(self, rsa_key: RsaKey) -> None: ...
+ def can_sign(self) -> bool: ...
+ def sign(self, msg_hash: Hash) -> bytes: ...
+ def verify(self, msg_hash: Hash, signature: bytes) -> None: ...
+
+def _EMSA_PKCS1_V1_5_ENCODE(msg_hash: Hash, emLen: int, with_hash_parameters: Optional[bool]=True) -> bytes: ...
+
+def new(rsa_key: RsaKey) -> PKCS115_SigScheme: ...
diff --git a/frozen_deps/Cryptodome/Signature/pss.py b/frozen_deps/Cryptodome/Signature/pss.py
new file mode 100644
index 0000000..0b05ed2
--- /dev/null
+++ b/frozen_deps/Cryptodome/Signature/pss.py
@@ -0,0 +1,386 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# 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 bchr, bord, iter_range
+import Cryptodome.Util.number
+from Cryptodome.Util.number import (ceil_div,
+ long_to_bytes,
+ bytes_to_long
+ )
+from Cryptodome.Util.strxor import strxor
+from Cryptodome import Random
+
+
+class PSS_SigScheme:
+ """A signature object for ``RSASSA-PSS``.
+ Do not instantiate directly.
+ Use :func:`Cryptodome.Signature.pss.new`.
+ """
+
+ def __init__(self, key, mgfunc, saltLen, randfunc):
+ """Initialize this PKCS#1 PSS signature scheme object.
+
+ :Parameters:
+ key : an RSA key object
+ If a private half is given, both signature and
+ verification are possible.
+ If a public half is given, only verification is possible.
+ mgfunc : callable
+ A mask generation function that accepts two parameters:
+ a string to use as seed, and the lenth of the mask to
+ generate, in bytes.
+ saltLen : integer
+ Length of the salt, in bytes.
+ randfunc : callable
+ A function that returns random bytes.
+ """
+
+ self._key = key
+ self._saltLen = saltLen
+ self._mgfunc = mgfunc
+ self._randfunc = randfunc
+
+ def can_sign(self):
+ """Return ``True`` if this object can be used to sign messages."""
+ return self._key.has_private()
+
+ def sign(self, msg_hash):
+ """Create the PKCS#1 PSS signature of a message.
+
+ This function is also called ``RSASSA-PSS-SIGN`` and
+ it is specified in
+ `section 8.1.1 of RFC8017 <https://tools.ietf.org/html/rfc8017#section-8.1.1>`_.
+
+ :parameter msg_hash:
+ This is an object from the :mod:`Cryptodome.Hash` package.
+ It has been used to digest the message to sign.
+ :type msg_hash: hash object
+
+ :return: the signature encoded as a *byte string*.
+ :raise ValueError: if the RSA key is not long enough for the given hash algorithm.
+ :raise TypeError: if the RSA key has no private half.
+ """
+
+ # Set defaults for salt length and mask generation function
+ if self._saltLen is None:
+ sLen = msg_hash.digest_size
+ else:
+ sLen = self._saltLen
+
+ if self._mgfunc is None:
+ mgf = lambda x, y: MGF1(x, y, msg_hash)
+ else:
+ mgf = self._mgfunc
+
+ modBits = Cryptodome.Util.number.size(self._key.n)
+
+ # See 8.1.1 in RFC3447
+ k = ceil_div(modBits, 8) # k is length in bytes of the modulus
+ # Step 1
+ em = _EMSA_PSS_ENCODE(msg_hash, modBits-1, self._randfunc, mgf, sLen)
+ # Step 2a (OS2IP)
+ em_int = bytes_to_long(em)
+ # Step 2b (RSASP1)
+ m_int = self._key._decrypt(em_int)
+ # Step 2c (I2OSP)
+ signature = long_to_bytes(m_int, k)
+ return signature
+
+ def verify(self, msg_hash, signature):
+ """Check if the PKCS#1 PSS signature over a message is valid.
+
+ This function is also called ``RSASSA-PSS-VERIFY`` and
+ it is specified in
+ `section 8.1.2 of RFC8037 <https://tools.ietf.org/html/rfc8017#section-8.1.2>`_.
+
+ :parameter msg_hash:
+ The hash that was carried out over the message. This is an object
+ belonging to the :mod:`Cryptodome.Hash` module.
+ :type parameter: hash object
+
+ :parameter signature:
+ The signature that needs to be validated.
+ :type signature: bytes
+
+ :raise ValueError: if the signature is not valid.
+ """
+
+ # Set defaults for salt length and mask generation function
+ if self._saltLen is None:
+ sLen = msg_hash.digest_size
+ else:
+ sLen = self._saltLen
+ if self._mgfunc:
+ mgf = self._mgfunc
+ else:
+ mgf = lambda x, y: MGF1(x, y, msg_hash)
+
+ modBits = Cryptodome.Util.number.size(self._key.n)
+
+ # See 8.1.2 in RFC3447
+ k = ceil_div(modBits, 8) # Convert from bits to bytes
+ # Step 1
+ if len(signature) != k:
+ raise ValueError("Incorrect signature")
+ # Step 2a (O2SIP)
+ signature_int = bytes_to_long(signature)
+ # Step 2b (RSAVP1)
+ em_int = self._key._encrypt(signature_int)
+ # Step 2c (I2OSP)
+ emLen = ceil_div(modBits - 1, 8)
+ em = long_to_bytes(em_int, emLen)
+ # Step 3/4
+ _EMSA_PSS_VERIFY(msg_hash, em, modBits-1, mgf, sLen)
+
+
+def MGF1(mgfSeed, maskLen, hash_gen):
+ """Mask Generation Function, described in `B.2.1 of RFC8017
+ <https://tools.ietf.org/html/rfc8017>`_.
+
+ :param mfgSeed:
+ seed from which the mask is generated
+ :type mfgSeed: byte string
+
+ :param maskLen:
+ intended length in bytes of the mask
+ :type maskLen: integer
+
+ :param hash_gen:
+ A module or a hash object from :mod:`Cryptodome.Hash`
+ :type hash_object:
+
+ :return: the mask, as a *byte string*
+ """
+
+ T = b""
+ for counter in iter_range(ceil_div(maskLen, hash_gen.digest_size)):
+ c = long_to_bytes(counter, 4)
+ hobj = hash_gen.new()
+ hobj.update(mgfSeed + c)
+ T = T + hobj.digest()
+ assert(len(T) >= maskLen)
+ return T[:maskLen]
+
+
+def _EMSA_PSS_ENCODE(mhash, emBits, randFunc, mgf, sLen):
+ r"""
+ Implement the ``EMSA-PSS-ENCODE`` function, as defined
+ in PKCS#1 v2.1 (RFC3447, 9.1.1).
+
+ The original ``EMSA-PSS-ENCODE`` actually accepts the message ``M``
+ as input, and hash it internally. Here, we expect that the message
+ has already been hashed instead.
+
+ :Parameters:
+ mhash : hash object
+ The hash object that holds the digest of the message being signed.
+ emBits : int
+ Maximum length of the final encoding, in bits.
+ randFunc : callable
+ An RNG function that accepts as only parameter an int, and returns
+ a string of random bytes, to be used as salt.
+ mgf : callable
+ A mask generation function that accepts two parameters: a string to
+ use as seed, and the lenth of the mask to generate, in bytes.
+ sLen : int
+ Length of the salt, in bytes.
+
+ :Return: An ``emLen`` byte long string that encodes the hash
+ (with ``emLen = \ceil(emBits/8)``).
+
+ :Raise ValueError:
+ When digest or salt length are too big.
+ """
+
+ emLen = ceil_div(emBits, 8)
+
+ # Bitmask of digits that fill up
+ lmask = 0
+ for i in iter_range(8*emLen-emBits):
+ lmask = lmask >> 1 | 0x80
+
+ # Step 1 and 2 have been already done
+ # Step 3
+ if emLen < mhash.digest_size+sLen+2:
+ raise ValueError("Digest or salt length are too long"
+ " for given key size.")
+ # Step 4
+ salt = randFunc(sLen)
+ # Step 5
+ m_prime = bchr(0)*8 + mhash.digest() + salt
+ # Step 6
+ h = mhash.new()
+ h.update(m_prime)
+ # Step 7
+ ps = bchr(0)*(emLen-sLen-mhash.digest_size-2)
+ # Step 8
+ db = ps + bchr(1) + salt
+ # Step 9
+ dbMask = mgf(h.digest(), emLen-mhash.digest_size-1)
+ # Step 10
+ maskedDB = strxor(db, dbMask)
+ # Step 11
+ maskedDB = bchr(bord(maskedDB[0]) & ~lmask) + maskedDB[1:]
+ # Step 12
+ em = maskedDB + h.digest() + bchr(0xBC)
+ return em
+
+
+def _EMSA_PSS_VERIFY(mhash, em, emBits, mgf, sLen):
+ """
+ Implement the ``EMSA-PSS-VERIFY`` function, as defined
+ in PKCS#1 v2.1 (RFC3447, 9.1.2).
+
+ ``EMSA-PSS-VERIFY`` actually accepts the message ``M`` as input,
+ and hash it internally. Here, we expect that the message has already
+ been hashed instead.
+
+ :Parameters:
+ mhash : hash object
+ The hash object that holds the digest of the message to be verified.
+ em : string
+ The signature to verify, therefore proving that the sender really
+ signed the message that was received.
+ emBits : int
+ Length of the final encoding (em), in bits.
+ mgf : callable
+ A mask generation function that accepts two parameters: a string to
+ use as seed, and the lenth of the mask to generate, in bytes.
+ sLen : int
+ Length of the salt, in bytes.
+
+ :Raise ValueError:
+ When the encoding is inconsistent, or the digest or salt lengths
+ are too big.
+ """
+
+ emLen = ceil_div(emBits, 8)
+
+ # Bitmask of digits that fill up
+ lmask = 0
+ for i in iter_range(8*emLen-emBits):
+ lmask = lmask >> 1 | 0x80
+
+ # Step 1 and 2 have been already done
+ # Step 3
+ if emLen < mhash.digest_size+sLen+2:
+ raise ValueError("Incorrect signature")
+ # Step 4
+ if ord(em[-1:]) != 0xBC:
+ raise ValueError("Incorrect signature")
+ # Step 5
+ maskedDB = em[:emLen-mhash.digest_size-1]
+ h = em[emLen-mhash.digest_size-1:-1]
+ # Step 6
+ if lmask & bord(em[0]):
+ raise ValueError("Incorrect signature")
+ # Step 7
+ dbMask = mgf(h, emLen-mhash.digest_size-1)
+ # Step 8
+ db = strxor(maskedDB, dbMask)
+ # Step 9
+ db = bchr(bord(db[0]) & ~lmask) + db[1:]
+ # Step 10
+ if not db.startswith(bchr(0)*(emLen-mhash.digest_size-sLen-2) + bchr(1)):
+ raise ValueError("Incorrect signature")
+ # Step 11
+ if sLen > 0:
+ salt = db[-sLen:]
+ else:
+ salt = b""
+ # Step 12
+ m_prime = bchr(0)*8 + mhash.digest() + salt
+ # Step 13
+ hobj = mhash.new()
+ hobj.update(m_prime)
+ hp = hobj.digest()
+ # Step 14
+ if h != hp:
+ raise ValueError("Incorrect signature")
+
+
+def new(rsa_key, **kwargs):
+ """Create an object for making or verifying PKCS#1 PSS signatures.
+
+ :parameter rsa_key:
+ The RSA key to use for signing or verifying the message.
+ This is a :class:`Cryptodome.PublicKey.RSA` object.
+ Signing is only possible when ``rsa_key`` is a **private** RSA key.
+ :type rsa_key: RSA object
+
+ :Keyword Arguments:
+
+ * *mask_func* (``callable``) --
+ A function that returns the mask (as `bytes`).
+ It must accept two parameters: a seed (as `bytes`)
+ and the length of the data to return.
+
+ If not specified, it will be the function :func:`MGF1` defined in
+ `RFC8017 <https://tools.ietf.org/html/rfc8017#page-67>`_ and
+ combined with the same hash algorithm applied to the
+ message to sign or verify.
+
+ If you want to use a different function, for instance still :func:`MGF1`
+ but together with another hash, you can do::
+
+ from Cryptodome.Hash import SHA256
+ from Cryptodome.Signature.pss import MGF1
+ mgf = lambda x, y: MGF1(x, y, SHA256)
+
+ * *salt_bytes* (``integer``) --
+ Length of the salt, in bytes.
+ It is a value between 0 and ``emLen - hLen - 2``, where ``emLen``
+ is the size of the RSA modulus and ``hLen`` is the size of the digest
+ applied to the message to sign or verify.
+
+ The salt is generated internally, you don't need to provide it.
+
+ If not specified, the salt length will be ``hLen``.
+ If it is zero, the signature scheme becomes deterministic.
+
+ Note that in some implementations such as OpenSSL the default
+ salt length is ``emLen - hLen - 2`` (even though it is not more
+ secure than ``hLen``).
+
+ * *rand_func* (``callable``) --
+ A function that returns random ``bytes``, of the desired length.
+ The default is :func:`Cryptodome.Random.get_random_bytes`.
+
+ :return: a :class:`PSS_SigScheme` signature object
+ """
+
+ mask_func = kwargs.pop("mask_func", None)
+ salt_len = kwargs.pop("salt_bytes", None)
+ rand_func = kwargs.pop("rand_func", None)
+ if rand_func is None:
+ rand_func = Random.get_random_bytes
+ if kwargs:
+ raise ValueError("Unknown keywords: " + str(kwargs.keys()))
+ return PSS_SigScheme(rsa_key, mask_func, salt_len, rand_func)
diff --git a/frozen_deps/Cryptodome/Signature/pss.pyi b/frozen_deps/Cryptodome/Signature/pss.pyi
new file mode 100644
index 0000000..9ca19ea
--- /dev/null
+++ b/frozen_deps/Cryptodome/Signature/pss.pyi
@@ -0,0 +1,30 @@
+from typing import Union, Callable, Optional
+from typing_extensions import Protocol
+
+from Cryptodome.PublicKey.RSA import RsaKey
+
+
+class Hash(Protocol):
+ def digest(self) -> bytes: ...
+ def update(self, bytes) -> None: ...
+
+
+class HashModule(Protocol):
+ @staticmethod
+ def new(data: Optional[bytes]) -> Hash: ...
+
+
+MaskFunction = Callable[[bytes, int, Union[Hash, HashModule]], bytes]
+RndFunction = Callable[[int], bytes]
+
+class PSS_SigScheme:
+ def __init__(self, key: RsaKey, mgfunc: RndFunction, saltLen: int, randfunc: RndFunction) -> None: ...
+ def can_sign(self) -> bool: ...
+ def sign(self, msg_hash: Hash) -> bytes: ...
+ def verify(self, msg_hash: Hash, signature: bytes) -> None: ...
+
+
+MGF1 : MaskFunction
+def _EMSA_PSS_ENCODE(mhash: Hash, emBits: int, randFunc: RndFunction, mgf:MaskFunction, sLen: int) -> str: ...
+def _EMSA_PSS_VERIFY(mhash: Hash, em: str, emBits: int, mgf: MaskFunction, sLen: int) -> None: ...
+def new(rsa_key: RsaKey, **kwargs: Union[MaskFunction, RndFunction, int]) -> PSS_SigScheme: ...
diff --git a/frozen_deps/Cryptodome/Util/Counter.py b/frozen_deps/Cryptodome/Util/Counter.py
new file mode 100644
index 0000000..423f91f
--- /dev/null
+++ b/frozen_deps/Cryptodome/Util/Counter.py
@@ -0,0 +1,70 @@
+# -*- coding: ascii -*-
+#
+# Util/Counter.py : Fast counter for use with CTR-mode ciphers
+#
+# Written in 2008 by Dwayne C. Litzenberger <[email protected]>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+def new(nbits, prefix=b"", suffix=b"", initial_value=1, little_endian=False, allow_wraparound=False):
+ """Create a stateful counter block function suitable for CTR encryption modes.
+
+ Each call to the function returns the next counter block.
+ Each counter block is made up by three parts:
+
+ +------+--------------+-------+
+ |prefix| counter value|postfix|
+ +------+--------------+-------+
+
+ The counter value is incremented by 1 at each call.
+
+ Args:
+ nbits (integer):
+ Length of the desired counter value, in bits. It must be a multiple of 8.
+ prefix (byte string):
+ The constant prefix of the counter block. By default, no prefix is
+ used.
+ suffix (byte string):
+ The constant postfix of the counter block. By default, no suffix is
+ used.
+ initial_value (integer):
+ The initial value of the counter. Default value is 1.
+ little_endian (boolean):
+ If ``True``, the counter number will be encoded in little endian format.
+ If ``False`` (default), in big endian format.
+ allow_wraparound (boolean):
+ This parameter is ignored.
+ Returns:
+ An object that can be passed with the :data:`counter` parameter to a CTR mode
+ cipher.
+
+ It must hold that *len(prefix) + nbits//8 + len(suffix)* matches the
+ block size of the underlying block cipher.
+ """
+
+ if (nbits % 8) != 0:
+ raise ValueError("'nbits' must be a multiple of 8")
+
+ # Ignore wraparound
+ return {"counter_len": nbits // 8,
+ "prefix": prefix,
+ "suffix": suffix,
+ "initial_value": initial_value,
+ "little_endian": little_endian
+ }
diff --git a/frozen_deps/Cryptodome/Util/Counter.pyi b/frozen_deps/Cryptodome/Util/Counter.pyi
new file mode 100644
index 0000000..fa2ffdd
--- /dev/null
+++ b/frozen_deps/Cryptodome/Util/Counter.pyi
@@ -0,0 +1,5 @@
+from typing import Optional, Union, Dict
+
+def new(nbits: int, prefix: Optional[bytes]=..., suffix: Optional[bytes]=..., initial_value: Optional[int]=1,
+ little_endian: Optional[bool]=False, allow_wraparound: Optional[bool]=False) -> \
+ Dict[str, Union[int, bytes, bool]]: ...
diff --git a/frozen_deps/Cryptodome/Util/Padding.py b/frozen_deps/Cryptodome/Util/Padding.py
new file mode 100644
index 0000000..1c353d1
--- /dev/null
+++ b/frozen_deps/Cryptodome/Util/Padding.py
@@ -0,0 +1,106 @@
+#
+# Util/Padding.py : Functions to manage padding
+#
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+__all__ = [ 'pad', 'unpad' ]
+
+from Cryptodome.Util.py3compat import *
+
+
+def pad(data_to_pad, block_size, style='pkcs7'):
+ """Apply standard padding.
+
+ Args:
+ data_to_pad (byte string):
+ The data that needs to be padded.
+ block_size (integer):
+ The block boundary to use for padding. The output length is guaranteed
+ to be a multiple of :data:`block_size`.
+ style (string):
+ Padding algorithm. It can be *'pkcs7'* (default), *'iso7816'* or *'x923'*.
+
+ Return:
+ byte string : the original data with the appropriate padding added at the end.
+ """
+
+ padding_len = block_size-len(data_to_pad)%block_size
+ if style == 'pkcs7':
+ padding = bchr(padding_len)*padding_len
+ elif style == 'x923':
+ padding = bchr(0)*(padding_len-1) + bchr(padding_len)
+ elif style == 'iso7816':
+ padding = bchr(128) + bchr(0)*(padding_len-1)
+ else:
+ raise ValueError("Unknown padding style")
+ return data_to_pad + padding
+
+
+def unpad(padded_data, block_size, style='pkcs7'):
+ """Remove standard padding.
+
+ Args:
+ padded_data (byte string):
+ A piece of data with padding that needs to be stripped.
+ block_size (integer):
+ The block boundary to use for padding. The input length
+ must be a multiple of :data:`block_size`.
+ style (string):
+ Padding algorithm. It can be *'pkcs7'* (default), *'iso7816'* or *'x923'*.
+ Return:
+ byte string : data without padding.
+ Raises:
+ ValueError: if the padding is incorrect.
+ """
+
+ pdata_len = len(padded_data)
+ if pdata_len % block_size:
+ raise ValueError("Input data is not padded")
+ if style in ('pkcs7', 'x923'):
+ padding_len = bord(padded_data[-1])
+ if padding_len<1 or padding_len>min(block_size, pdata_len):
+ raise ValueError("Padding is incorrect.")
+ if style == 'pkcs7':
+ if padded_data[-padding_len:]!=bchr(padding_len)*padding_len:
+ raise ValueError("PKCS#7 padding is incorrect.")
+ else:
+ if padded_data[-padding_len:-1]!=bchr(0)*(padding_len-1):
+ raise ValueError("ANSI X.923 padding is incorrect.")
+ elif style == 'iso7816':
+ padding_len = pdata_len - padded_data.rfind(bchr(128))
+ if padding_len<1 or padding_len>min(block_size, pdata_len):
+ raise ValueError("Padding is incorrect.")
+ if padding_len>1 and padded_data[1-padding_len:]!=bchr(0)*(padding_len-1):
+ raise ValueError("ISO 7816-4 padding is incorrect.")
+ else:
+ raise ValueError("Unknown padding style")
+ return padded_data[:-padding_len]
+
diff --git a/frozen_deps/Cryptodome/Util/Padding.pyi b/frozen_deps/Cryptodome/Util/Padding.pyi
new file mode 100644
index 0000000..4d8d30d
--- /dev/null
+++ b/frozen_deps/Cryptodome/Util/Padding.pyi
@@ -0,0 +1,6 @@
+from typing import Optional
+
+__all__ = [ 'pad', 'unpad' ]
+
+def pad(data_to_pad: bytes, block_size: int, style: Optional[str]='pkcs7') -> bytes: ...
+def unpad(padded_data: bytes, block_size: int, style: Optional[str]='pkcs7') -> bytes: ... \ No newline at end of file
diff --git a/frozen_deps/Cryptodome/Util/RFC1751.py b/frozen_deps/Cryptodome/Util/RFC1751.py
new file mode 100644
index 0000000..10859c3
--- /dev/null
+++ b/frozen_deps/Cryptodome/Util/RFC1751.py
@@ -0,0 +1,386 @@
+# rfc1751.py : Converts between 128-bit strings and a human-readable
+# sequence of words, as defined in RFC1751: "A Convention for
+# Human-Readable 128-bit Keys", by Daniel L. McDonald.
+#
+# Part of the Python Cryptography Toolkit
+#
+# Written by Andrew M. Kuchling and others
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+from __future__ import print_function
+
+import binascii
+
+from Cryptodome.Util.py3compat import bord, bchr
+
+binary = {0: '0000', 1: '0001', 2: '0010', 3: '0011', 4: '0100', 5: '0101',
+ 6: '0110', 7: '0111', 8: '1000', 9: '1001', 10: '1010', 11: '1011',
+ 12: '1100', 13: '1101', 14: '1110', 15: '1111'}
+
+
+def _key2bin(s):
+ "Convert a key into a string of binary digits"
+ kl = map(lambda x: bord(x), s)
+ kl = map(lambda x: binary[x >> 4] + binary[x & 15], kl)
+ return ''.join(kl)
+
+
+def _extract(key, start, length):
+ """Extract a bitstring(2.x)/bytestring(2.x) from a string of binary digits, and return its
+ numeric value."""
+
+ result = 0
+ for y in key[start:start+length]:
+ result = result * 2 + ord(y) - 48
+ return result
+
+
+def key_to_english(key):
+ """Transform an arbitrary key into a string containing English words.
+
+ Example::
+
+ >>> from Cryptodome.Util.RFC1751 import key_to_english
+ >>> key_to_english(b'66666666')
+ 'RAM LOIS GOAD CREW CARE HIT'
+
+ Args:
+ key (byte string):
+ The key to convert. Its length must be a multiple of 8.
+ Return:
+ A string of English words.
+ """
+
+ if len(key) % 8 != 0:
+ raise ValueError('The length of the key must be a multiple of 8.')
+
+ english = ''
+ for index in range(0, len(key), 8): # Loop over 8-byte subkeys
+ subkey = key[index:index + 8]
+ # Compute the parity of the key
+ skbin = _key2bin(subkey)
+ p = 0
+ for i in range(0, 64, 2):
+ p = p + _extract(skbin, i, 2)
+ # Append parity bits to the subkey
+ skbin = _key2bin(subkey + bchr((p << 6) & 255))
+ for i in range(0, 64, 11):
+ english = english + wordlist[_extract(skbin, i, 11)] + ' '
+
+ return english.strip()
+
+
+def english_to_key(s):
+ """Transform a string into a corresponding key.
+
+ Example::
+
+ >>> from Cryptodome.Util.RFC1751 import english_to_key
+ >>> english_to_key('RAM LOIS GOAD CREW CARE HIT')
+ b'66666666'
+
+ Args:
+ s (string): the string with the words separated by whitespace;
+ the number of words must be a multiple of 6.
+ Return:
+ A byte string.
+ """
+
+ L = s.upper().split()
+ key = b''
+ for index in range(0, len(L), 6):
+ sublist = L[index:index + 6]
+ char = 9 * [0]
+ bits = 0
+ for i in sublist:
+ index = wordlist.index(i)
+ shift = (8 - (bits + 11) % 8) % 8
+ y = index << shift
+ cl, cc, cr = (y >> 16), (y >> 8) & 0xff, y & 0xff
+ if (shift > 5):
+ char[bits >> 3] = char[bits >> 3] | cl
+ char[(bits >> 3) + 1] = char[(bits >> 3) + 1] | cc
+ char[(bits >> 3) + 2] = char[(bits >> 3) + 2] | cr
+ elif shift > -3:
+ char[bits >> 3] = char[bits >> 3] | cc
+ char[(bits >> 3) + 1] = char[(bits >> 3) + 1] | cr
+ else:
+ char[bits >> 3] = char[bits >> 3] | cr
+ bits = bits + 11
+
+ subkey = b''
+ for y in char:
+ subkey = subkey + bchr(y)
+
+ # Check the parity of the resulting key
+ skbin = _key2bin(subkey)
+ p = 0
+ for i in range(0, 64, 2):
+ p = p + _extract(skbin, i, 2)
+ if (p & 3) != _extract(skbin, 64, 2):
+ raise ValueError("Parity error in resulting key")
+ key = key + subkey[0:8]
+ return key
+
+
+wordlist = [
+ "A", "ABE", "ACE", "ACT", "AD", "ADA", "ADD",
+ "AGO", "AID", "AIM", "AIR", "ALL", "ALP", "AM", "AMY", "AN", "ANA",
+ "AND", "ANN", "ANT", "ANY", "APE", "APS", "APT", "ARC", "ARE", "ARK",
+ "ARM", "ART", "AS", "ASH", "ASK", "AT", "ATE", "AUG", "AUK", "AVE",
+ "AWE", "AWK", "AWL", "AWN", "AX", "AYE", "BAD", "BAG", "BAH", "BAM",
+ "BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", "BEN", "BET",
+ "BEY", "BIB", "BID", "BIG", "BIN", "BIT", "BOB", "BOG", "BON", "BOO",
+ "BOP", "BOW", "BOY", "BUB", "BUD", "BUG", "BUM", "BUN", "BUS", "BUT",
+ "BUY", "BY", "BYE", "CAB", "CAL", "CAM", "CAN", "CAP", "CAR", "CAT",
+ "CAW", "COD", "COG", "COL", "CON", "COO", "COP", "COT", "COW", "COY",
+ "CRY", "CUB", "CUE", "CUP", "CUR", "CUT", "DAB", "DAD", "DAM", "DAN",
+ "DAR", "DAY", "DEE", "DEL", "DEN", "DES", "DEW", "DID", "DIE", "DIG",
+ "DIN", "DIP", "DO", "DOE", "DOG", "DON", "DOT", "DOW", "DRY", "DUB",
+ "DUD", "DUE", "DUG", "DUN", "EAR", "EAT", "ED", "EEL", "EGG", "EGO",
+ "ELI", "ELK", "ELM", "ELY", "EM", "END", "EST", "ETC", "EVA", "EVE",
+ "EWE", "EYE", "FAD", "FAN", "FAR", "FAT", "FAY", "FED", "FEE", "FEW",
+ "FIB", "FIG", "FIN", "FIR", "FIT", "FLO", "FLY", "FOE", "FOG", "FOR",
+ "FRY", "FUM", "FUN", "FUR", "GAB", "GAD", "GAG", "GAL", "GAM", "GAP",
+ "GAS", "GAY", "GEE", "GEL", "GEM", "GET", "GIG", "GIL", "GIN", "GO",
+ "GOT", "GUM", "GUN", "GUS", "GUT", "GUY", "GYM", "GYP", "HA", "HAD",
+ "HAL", "HAM", "HAN", "HAP", "HAS", "HAT", "HAW", "HAY", "HE", "HEM",
+ "HEN", "HER", "HEW", "HEY", "HI", "HID", "HIM", "HIP", "HIS", "HIT",
+ "HO", "HOB", "HOC", "HOE", "HOG", "HOP", "HOT", "HOW", "HUB", "HUE",
+ "HUG", "HUH", "HUM", "HUT", "I", "ICY", "IDA", "IF", "IKE", "ILL",
+ "INK", "INN", "IO", "ION", "IQ", "IRA", "IRE", "IRK", "IS", "IT",
+ "ITS", "IVY", "JAB", "JAG", "JAM", "JAN", "JAR", "JAW", "JAY", "JET",
+ "JIG", "JIM", "JO", "JOB", "JOE", "JOG", "JOT", "JOY", "JUG", "JUT",
+ "KAY", "KEG", "KEN", "KEY", "KID", "KIM", "KIN", "KIT", "LA", "LAB",
+ "LAC", "LAD", "LAG", "LAM", "LAP", "LAW", "LAY", "LEA", "LED", "LEE",
+ "LEG", "LEN", "LEO", "LET", "LEW", "LID", "LIE", "LIN", "LIP", "LIT",
+ "LO", "LOB", "LOG", "LOP", "LOS", "LOT", "LOU", "LOW", "LOY", "LUG",
+ "LYE", "MA", "MAC", "MAD", "MAE", "MAN", "MAO", "MAP", "MAT", "MAW",
+ "MAY", "ME", "MEG", "MEL", "MEN", "MET", "MEW", "MID", "MIN", "MIT",
+ "MOB", "MOD", "MOE", "MOO", "MOP", "MOS", "MOT", "MOW", "MUD", "MUG",
+ "MUM", "MY", "NAB", "NAG", "NAN", "NAP", "NAT", "NAY", "NE", "NED",
+ "NEE", "NET", "NEW", "NIB", "NIL", "NIP", "NIT", "NO", "NOB", "NOD",
+ "NON", "NOR", "NOT", "NOV", "NOW", "NU", "NUN", "NUT", "O", "OAF",
+ "OAK", "OAR", "OAT", "ODD", "ODE", "OF", "OFF", "OFT", "OH", "OIL",
+ "OK", "OLD", "ON", "ONE", "OR", "ORB", "ORE", "ORR", "OS", "OTT",
+ "OUR", "OUT", "OVA", "OW", "OWE", "OWL", "OWN", "OX", "PA", "PAD",
+ "PAL", "PAM", "PAN", "PAP", "PAR", "PAT", "PAW", "PAY", "PEA", "PEG",
+ "PEN", "PEP", "PER", "PET", "PEW", "PHI", "PI", "PIE", "PIN", "PIT",
+ "PLY", "PO", "POD", "POE", "POP", "POT", "POW", "PRO", "PRY", "PUB",
+ "PUG", "PUN", "PUP", "PUT", "QUO", "RAG", "RAM", "RAN", "RAP", "RAT",
+ "RAW", "RAY", "REB", "RED", "REP", "RET", "RIB", "RID", "RIG", "RIM",
+ "RIO", "RIP", "ROB", "ROD", "ROE", "RON", "ROT", "ROW", "ROY", "RUB",
+ "RUE", "RUG", "RUM", "RUN", "RYE", "SAC", "SAD", "SAG", "SAL", "SAM",
+ "SAN", "SAP", "SAT", "SAW", "SAY", "SEA", "SEC", "SEE", "SEN", "SET",
+ "SEW", "SHE", "SHY", "SIN", "SIP", "SIR", "SIS", "SIT", "SKI", "SKY",
+ "SLY", "SO", "SOB", "SOD", "SON", "SOP", "SOW", "SOY", "SPA", "SPY",
+ "SUB", "SUD", "SUE", "SUM", "SUN", "SUP", "TAB", "TAD", "TAG", "TAN",
+ "TAP", "TAR", "TEA", "TED", "TEE", "TEN", "THE", "THY", "TIC", "TIE",
+ "TIM", "TIN", "TIP", "TO", "TOE", "TOG", "TOM", "TON", "TOO", "TOP",
+ "TOW", "TOY", "TRY", "TUB", "TUG", "TUM", "TUN", "TWO", "UN", "UP",
+ "US", "USE", "VAN", "VAT", "VET", "VIE", "WAD", "WAG", "WAR", "WAS",
+ "WAY", "WE", "WEB", "WED", "WEE", "WET", "WHO", "WHY", "WIN", "WIT",
+ "WOK", "WON", "WOO", "WOW", "WRY", "WU", "YAM", "YAP", "YAW", "YE",
+ "YEA", "YES", "YET", "YOU", "ABED", "ABEL", "ABET", "ABLE", "ABUT",
+ "ACHE", "ACID", "ACME", "ACRE", "ACTA", "ACTS", "ADAM", "ADDS",
+ "ADEN", "AFAR", "AFRO", "AGEE", "AHEM", "AHOY", "AIDA", "AIDE",
+ "AIDS", "AIRY", "AJAR", "AKIN", "ALAN", "ALEC", "ALGA", "ALIA",
+ "ALLY", "ALMA", "ALOE", "ALSO", "ALTO", "ALUM", "ALVA", "AMEN",
+ "AMES", "AMID", "AMMO", "AMOK", "AMOS", "AMRA", "ANDY", "ANEW",
+ "ANNA", "ANNE", "ANTE", "ANTI", "AQUA", "ARAB", "ARCH", "AREA",
+ "ARGO", "ARID", "ARMY", "ARTS", "ARTY", "ASIA", "ASKS", "ATOM",
+ "AUNT", "AURA", "AUTO", "AVER", "AVID", "AVIS", "AVON", "AVOW",
+ "AWAY", "AWRY", "BABE", "BABY", "BACH", "BACK", "BADE", "BAIL",
+ "BAIT", "BAKE", "BALD", "BALE", "BALI", "BALK", "BALL", "BALM",
+ "BAND", "BANE", "BANG", "BANK", "BARB", "BARD", "BARE", "BARK",
+ "BARN", "BARR", "BASE", "BASH", "BASK", "BASS", "BATE", "BATH",
+ "BAWD", "BAWL", "BEAD", "BEAK", "BEAM", "BEAN", "BEAR", "BEAT",
+ "BEAU", "BECK", "BEEF", "BEEN", "BEER",
+ "BEET", "BELA", "BELL", "BELT", "BEND", "BENT", "BERG", "BERN",
+ "BERT", "BESS", "BEST", "BETA", "BETH", "BHOY", "BIAS", "BIDE",
+ "BIEN", "BILE", "BILK", "BILL", "BIND", "BING", "BIRD", "BITE",
+ "BITS", "BLAB", "BLAT", "BLED", "BLEW", "BLOB", "BLOC", "BLOT",
+ "BLOW", "BLUE", "BLUM", "BLUR", "BOAR", "BOAT", "BOCA", "BOCK",
+ "BODE", "BODY", "BOGY", "BOHR", "BOIL", "BOLD", "BOLO", "BOLT",
+ "BOMB", "BONA", "BOND", "BONE", "BONG", "BONN", "BONY", "BOOK",
+ "BOOM", "BOON", "BOOT", "BORE", "BORG", "BORN", "BOSE", "BOSS",
+ "BOTH", "BOUT", "BOWL", "BOYD", "BRAD", "BRAE", "BRAG", "BRAN",
+ "BRAY", "BRED", "BREW", "BRIG", "BRIM", "BROW", "BUCK", "BUDD",
+ "BUFF", "BULB", "BULK", "BULL", "BUNK", "BUNT", "BUOY", "BURG",
+ "BURL", "BURN", "BURR", "BURT", "BURY", "BUSH", "BUSS", "BUST",
+ "BUSY", "BYTE", "CADY", "CAFE", "CAGE", "CAIN", "CAKE", "CALF",
+ "CALL", "CALM", "CAME", "CANE", "CANT", "CARD", "CARE", "CARL",
+ "CARR", "CART", "CASE", "CASH", "CASK", "CAST", "CAVE", "CEIL",
+ "CELL", "CENT", "CERN", "CHAD", "CHAR", "CHAT", "CHAW", "CHEF",
+ "CHEN", "CHEW", "CHIC", "CHIN", "CHOU", "CHOW", "CHUB", "CHUG",
+ "CHUM", "CITE", "CITY", "CLAD", "CLAM", "CLAN", "CLAW", "CLAY",
+ "CLOD", "CLOG", "CLOT", "CLUB", "CLUE", "COAL", "COAT", "COCA",
+ "COCK", "COCO", "CODA", "CODE", "CODY", "COED", "COIL", "COIN",
+ "COKE", "COLA", "COLD", "COLT", "COMA", "COMB", "COME", "COOK",
+ "COOL", "COON", "COOT", "CORD", "CORE", "CORK", "CORN", "COST",
+ "COVE", "COWL", "CRAB", "CRAG", "CRAM", "CRAY", "CREW", "CRIB",
+ "CROW", "CRUD", "CUBA", "CUBE", "CUFF", "CULL", "CULT", "CUNY",
+ "CURB", "CURD", "CURE", "CURL", "CURT", "CUTS", "DADE", "DALE",
+ "DAME", "DANA", "DANE", "DANG", "DANK", "DARE", "DARK", "DARN",
+ "DART", "DASH", "DATA", "DATE", "DAVE", "DAVY", "DAWN", "DAYS",
+ "DEAD", "DEAF", "DEAL", "DEAN", "DEAR", "DEBT", "DECK", "DEED",
+ "DEEM", "DEER", "DEFT", "DEFY", "DELL", "DENT", "DENY", "DESK",
+ "DIAL", "DICE", "DIED", "DIET", "DIME", "DINE", "DING", "DINT",
+ "DIRE", "DIRT", "DISC", "DISH", "DISK", "DIVE", "DOCK", "DOES",
+ "DOLE", "DOLL", "DOLT", "DOME", "DONE", "DOOM", "DOOR", "DORA",
+ "DOSE", "DOTE", "DOUG", "DOUR", "DOVE", "DOWN", "DRAB", "DRAG",
+ "DRAM", "DRAW", "DREW", "DRUB", "DRUG", "DRUM", "DUAL", "DUCK",
+ "DUCT", "DUEL", "DUET", "DUKE", "DULL", "DUMB", "DUNE", "DUNK",
+ "DUSK", "DUST", "DUTY", "EACH", "EARL", "EARN", "EASE", "EAST",
+ "EASY", "EBEN", "ECHO", "EDDY", "EDEN", "EDGE", "EDGY", "EDIT",
+ "EDNA", "EGAN", "ELAN", "ELBA", "ELLA", "ELSE", "EMIL", "EMIT",
+ "EMMA", "ENDS", "ERIC", "EROS", "EVEN", "EVER", "EVIL", "EYED",
+ "FACE", "FACT", "FADE", "FAIL", "FAIN", "FAIR", "FAKE", "FALL",
+ "FAME", "FANG", "FARM", "FAST", "FATE", "FAWN", "FEAR", "FEAT",
+ "FEED", "FEEL", "FEET", "FELL", "FELT", "FEND", "FERN", "FEST",
+ "FEUD", "FIEF", "FIGS", "FILE", "FILL", "FILM", "FIND", "FINE",
+ "FINK", "FIRE", "FIRM", "FISH", "FISK", "FIST", "FITS", "FIVE",
+ "FLAG", "FLAK", "FLAM", "FLAT", "FLAW", "FLEA", "FLED", "FLEW",
+ "FLIT", "FLOC", "FLOG", "FLOW", "FLUB", "FLUE", "FOAL", "FOAM",
+ "FOGY", "FOIL", "FOLD", "FOLK", "FOND", "FONT", "FOOD", "FOOL",
+ "FOOT", "FORD", "FORE", "FORK", "FORM", "FORT", "FOSS", "FOUL",
+ "FOUR", "FOWL", "FRAU", "FRAY", "FRED", "FREE", "FRET", "FREY",
+ "FROG", "FROM", "FUEL", "FULL", "FUME", "FUND", "FUNK", "FURY",
+ "FUSE", "FUSS", "GAFF", "GAGE", "GAIL", "GAIN", "GAIT", "GALA",
+ "GALE", "GALL", "GALT", "GAME", "GANG", "GARB", "GARY", "GASH",
+ "GATE", "GAUL", "GAUR", "GAVE", "GAWK", "GEAR", "GELD", "GENE",
+ "GENT", "GERM", "GETS", "GIBE", "GIFT", "GILD", "GILL", "GILT",
+ "GINA", "GIRD", "GIRL", "GIST", "GIVE", "GLAD", "GLEE", "GLEN",
+ "GLIB", "GLOB", "GLOM", "GLOW", "GLUE", "GLUM", "GLUT", "GOAD",
+ "GOAL", "GOAT", "GOER", "GOES", "GOLD", "GOLF", "GONE", "GONG",
+ "GOOD", "GOOF", "GORE", "GORY", "GOSH", "GOUT", "GOWN", "GRAB",
+ "GRAD", "GRAY", "GREG", "GREW", "GREY", "GRID", "GRIM", "GRIN",
+ "GRIT", "GROW", "GRUB", "GULF", "GULL", "GUNK", "GURU", "GUSH",
+ "GUST", "GWEN", "GWYN", "HAAG", "HAAS", "HACK", "HAIL", "HAIR",
+ "HALE", "HALF", "HALL", "HALO", "HALT", "HAND", "HANG", "HANK",
+ "HANS", "HARD", "HARK", "HARM", "HART", "HASH", "HAST", "HATE",
+ "HATH", "HAUL", "HAVE", "HAWK", "HAYS", "HEAD", "HEAL", "HEAR",
+ "HEAT", "HEBE", "HECK", "HEED", "HEEL", "HEFT", "HELD", "HELL",
+ "HELM", "HERB", "HERD", "HERE", "HERO", "HERS", "HESS", "HEWN",
+ "HICK", "HIDE", "HIGH", "HIKE", "HILL", "HILT", "HIND", "HINT",
+ "HIRE", "HISS", "HIVE", "HOBO", "HOCK", "HOFF", "HOLD", "HOLE",
+ "HOLM", "HOLT", "HOME", "HONE", "HONK", "HOOD", "HOOF", "HOOK",
+ "HOOT", "HORN", "HOSE", "HOST", "HOUR", "HOVE", "HOWE", "HOWL",
+ "HOYT", "HUCK", "HUED", "HUFF", "HUGE", "HUGH", "HUGO", "HULK",
+ "HULL", "HUNK", "HUNT", "HURD", "HURL", "HURT", "HUSH", "HYDE",
+ "HYMN", "IBIS", "ICON", "IDEA", "IDLE", "IFFY", "INCA", "INCH",
+ "INTO", "IONS", "IOTA", "IOWA", "IRIS", "IRMA", "IRON", "ISLE",
+ "ITCH", "ITEM", "IVAN", "JACK", "JADE", "JAIL", "JAKE", "JANE",
+ "JAVA", "JEAN", "JEFF", "JERK", "JESS", "JEST", "JIBE", "JILL",
+ "JILT", "JIVE", "JOAN", "JOBS", "JOCK", "JOEL", "JOEY", "JOHN",
+ "JOIN", "JOKE", "JOLT", "JOVE", "JUDD", "JUDE", "JUDO", "JUDY",
+ "JUJU", "JUKE", "JULY", "JUNE", "JUNK", "JUNO", "JURY", "JUST",
+ "JUTE", "KAHN", "KALE", "KANE", "KANT", "KARL", "KATE", "KEEL",
+ "KEEN", "KENO", "KENT", "KERN", "KERR", "KEYS", "KICK", "KILL",
+ "KIND", "KING", "KIRK", "KISS", "KITE", "KLAN", "KNEE", "KNEW",
+ "KNIT", "KNOB", "KNOT", "KNOW", "KOCH", "KONG", "KUDO", "KURD",
+ "KURT", "KYLE", "LACE", "LACK", "LACY", "LADY", "LAID", "LAIN",
+ "LAIR", "LAKE", "LAMB", "LAME", "LAND", "LANE", "LANG", "LARD",
+ "LARK", "LASS", "LAST", "LATE", "LAUD", "LAVA", "LAWN", "LAWS",
+ "LAYS", "LEAD", "LEAF", "LEAK", "LEAN", "LEAR", "LEEK", "LEER",
+ "LEFT", "LEND", "LENS", "LENT", "LEON", "LESK", "LESS", "LEST",
+ "LETS", "LIAR", "LICE", "LICK", "LIED", "LIEN", "LIES", "LIEU",
+ "LIFE", "LIFT", "LIKE", "LILA", "LILT", "LILY", "LIMA", "LIMB",
+ "LIME", "LIND", "LINE", "LINK", "LINT", "LION", "LISA", "LIST",
+ "LIVE", "LOAD", "LOAF", "LOAM", "LOAN", "LOCK", "LOFT", "LOGE",
+ "LOIS", "LOLA", "LONE", "LONG", "LOOK", "LOON", "LOOT", "LORD",
+ "LORE", "LOSE", "LOSS", "LOST", "LOUD", "LOVE", "LOWE", "LUCK",
+ "LUCY", "LUGE", "LUKE", "LULU", "LUND", "LUNG", "LURA", "LURE",
+ "LURK", "LUSH", "LUST", "LYLE", "LYNN", "LYON", "LYRA", "MACE",
+ "MADE", "MAGI", "MAID", "MAIL", "MAIN", "MAKE", "MALE", "MALI",
+ "MALL", "MALT", "MANA", "MANN", "MANY", "MARC", "MARE", "MARK",
+ "MARS", "MART", "MARY", "MASH", "MASK", "MASS", "MAST", "MATE",
+ "MATH", "MAUL", "MAYO", "MEAD", "MEAL", "MEAN", "MEAT", "MEEK",
+ "MEET", "MELD", "MELT", "MEMO", "MEND", "MENU", "MERT", "MESH",
+ "MESS", "MICE", "MIKE", "MILD", "MILE", "MILK", "MILL", "MILT",
+ "MIMI", "MIND", "MINE", "MINI", "MINK", "MINT", "MIRE", "MISS",
+ "MIST", "MITE", "MITT", "MOAN", "MOAT", "MOCK", "MODE", "MOLD",
+ "MOLE", "MOLL", "MOLT", "MONA", "MONK", "MONT", "MOOD", "MOON",
+ "MOOR", "MOOT", "MORE", "MORN", "MORT", "MOSS", "MOST", "MOTH",
+ "MOVE", "MUCH", "MUCK", "MUDD", "MUFF", "MULE", "MULL", "MURK",
+ "MUSH", "MUST", "MUTE", "MUTT", "MYRA", "MYTH", "NAGY", "NAIL",
+ "NAIR", "NAME", "NARY", "NASH", "NAVE", "NAVY", "NEAL", "NEAR",
+ "NEAT", "NECK", "NEED", "NEIL", "NELL", "NEON", "NERO", "NESS",
+ "NEST", "NEWS", "NEWT", "NIBS", "NICE", "NICK", "NILE", "NINA",
+ "NINE", "NOAH", "NODE", "NOEL", "NOLL", "NONE", "NOOK", "NOON",
+ "NORM", "NOSE", "NOTE", "NOUN", "NOVA", "NUDE", "NULL", "NUMB",
+ "OATH", "OBEY", "OBOE", "ODIN", "OHIO", "OILY", "OINT", "OKAY",
+ "OLAF", "OLDY", "OLGA", "OLIN", "OMAN", "OMEN", "OMIT", "ONCE",
+ "ONES", "ONLY", "ONTO", "ONUS", "ORAL", "ORGY", "OSLO", "OTIS",
+ "OTTO", "OUCH", "OUST", "OUTS", "OVAL", "OVEN", "OVER", "OWLY",
+ "OWNS", "QUAD", "QUIT", "QUOD", "RACE", "RACK", "RACY", "RAFT",
+ "RAGE", "RAID", "RAIL", "RAIN", "RAKE", "RANK", "RANT", "RARE",
+ "RASH", "RATE", "RAVE", "RAYS", "READ", "REAL", "REAM", "REAR",
+ "RECK", "REED", "REEF", "REEK", "REEL", "REID", "REIN", "RENA",
+ "REND", "RENT", "REST", "RICE", "RICH", "RICK", "RIDE", "RIFT",
+ "RILL", "RIME", "RING", "RINK", "RISE", "RISK", "RITE", "ROAD",
+ "ROAM", "ROAR", "ROBE", "ROCK", "RODE", "ROIL", "ROLL", "ROME",
+ "ROOD", "ROOF", "ROOK", "ROOM", "ROOT", "ROSA", "ROSE", "ROSS",
+ "ROSY", "ROTH", "ROUT", "ROVE", "ROWE", "ROWS", "RUBE", "RUBY",
+ "RUDE", "RUDY", "RUIN", "RULE", "RUNG", "RUNS", "RUNT", "RUSE",
+ "RUSH", "RUSK", "RUSS", "RUST", "RUTH", "SACK", "SAFE", "SAGE",
+ "SAID", "SAIL", "SALE", "SALK", "SALT", "SAME", "SAND", "SANE",
+ "SANG", "SANK", "SARA", "SAUL", "SAVE", "SAYS", "SCAN", "SCAR",
+ "SCAT", "SCOT", "SEAL", "SEAM", "SEAR", "SEAT", "SEED", "SEEK",
+ "SEEM", "SEEN", "SEES", "SELF", "SELL", "SEND", "SENT", "SETS",
+ "SEWN", "SHAG", "SHAM", "SHAW", "SHAY", "SHED", "SHIM", "SHIN",
+ "SHOD", "SHOE", "SHOT", "SHOW", "SHUN", "SHUT", "SICK", "SIDE",
+ "SIFT", "SIGH", "SIGN", "SILK", "SILL", "SILO", "SILT", "SINE",
+ "SING", "SINK", "SIRE", "SITE", "SITS", "SITU", "SKAT", "SKEW",
+ "SKID", "SKIM", "SKIN", "SKIT", "SLAB", "SLAM", "SLAT", "SLAY",
+ "SLED", "SLEW", "SLID", "SLIM", "SLIT", "SLOB", "SLOG", "SLOT",
+ "SLOW", "SLUG", "SLUM", "SLUR", "SMOG", "SMUG", "SNAG", "SNOB",
+ "SNOW", "SNUB", "SNUG", "SOAK", "SOAR", "SOCK", "SODA", "SOFA",
+ "SOFT", "SOIL", "SOLD", "SOME", "SONG", "SOON", "SOOT", "SORE",
+ "SORT", "SOUL", "SOUR", "SOWN", "STAB", "STAG", "STAN", "STAR",
+ "STAY", "STEM", "STEW", "STIR", "STOW", "STUB", "STUN", "SUCH",
+ "SUDS", "SUIT", "SULK", "SUMS", "SUNG", "SUNK", "SURE", "SURF",
+ "SWAB", "SWAG", "SWAM", "SWAN", "SWAT", "SWAY", "SWIM", "SWUM",
+ "TACK", "TACT", "TAIL", "TAKE", "TALE", "TALK", "TALL", "TANK",
+ "TASK", "TATE", "TAUT", "TEAL", "TEAM", "TEAR", "TECH", "TEEM",
+ "TEEN", "TEET", "TELL", "TEND", "TENT", "TERM", "TERN", "TESS",
+ "TEST", "THAN", "THAT", "THEE", "THEM", "THEN", "THEY", "THIN",
+ "THIS", "THUD", "THUG", "TICK", "TIDE", "TIDY", "TIED", "TIER",
+ "TILE", "TILL", "TILT", "TIME", "TINA", "TINE", "TINT", "TINY",
+ "TIRE", "TOAD", "TOGO", "TOIL", "TOLD", "TOLL", "TONE", "TONG",
+ "TONY", "TOOK", "TOOL", "TOOT", "TORE", "TORN", "TOTE", "TOUR",
+ "TOUT", "TOWN", "TRAG", "TRAM", "TRAY", "TREE", "TREK", "TRIG",
+ "TRIM", "TRIO", "TROD", "TROT", "TROY", "TRUE", "TUBA", "TUBE",
+ "TUCK", "TUFT", "TUNA", "TUNE", "TUNG", "TURF", "TURN", "TUSK",
+ "TWIG", "TWIN", "TWIT", "ULAN", "UNIT", "URGE", "USED", "USER",
+ "USES", "UTAH", "VAIL", "VAIN", "VALE", "VARY", "VASE", "VAST",
+ "VEAL", "VEDA", "VEIL", "VEIN", "VEND", "VENT", "VERB", "VERY",
+ "VETO", "VICE", "VIEW", "VINE", "VISE", "VOID", "VOLT", "VOTE",
+ "WACK", "WADE", "WAGE", "WAIL", "WAIT", "WAKE", "WALE", "WALK",
+ "WALL", "WALT", "WAND", "WANE", "WANG", "WANT", "WARD", "WARM",
+ "WARN", "WART", "WASH", "WAST", "WATS", "WATT", "WAVE", "WAVY",
+ "WAYS", "WEAK", "WEAL", "WEAN", "WEAR", "WEED", "WEEK", "WEIR",
+ "WELD", "WELL", "WELT", "WENT", "WERE", "WERT", "WEST", "WHAM",
+ "WHAT", "WHEE", "WHEN", "WHET", "WHOA", "WHOM", "WICK", "WIFE",
+ "WILD", "WILL", "WIND", "WINE", "WING", "WINK", "WINO", "WIRE",
+ "WISE", "WISH", "WITH", "WOLF", "WONT", "WOOD", "WOOL", "WORD",
+ "WORE", "WORK", "WORM", "WORN", "WOVE", "WRIT", "WYNN", "YALE",
+ "YANG", "YANK", "YARD", "YARN", "YAWL", "YAWN", "YEAH", "YEAR",
+ "YELL", "YOGA", "YOKE" ]
diff --git a/frozen_deps/Cryptodome/Util/RFC1751.pyi b/frozen_deps/Cryptodome/Util/RFC1751.pyi
new file mode 100644
index 0000000..6ad07ff
--- /dev/null
+++ b/frozen_deps/Cryptodome/Util/RFC1751.pyi
@@ -0,0 +1,7 @@
+from typing import Dict, List
+
+binary: Dict[int, str]
+wordlist: List[str]
+
+def key_to_english(key: bytes) -> str: ...
+def english_to_key(s: str) -> bytes: ...
diff --git a/frozen_deps/Cryptodome/Util/__init__.py b/frozen_deps/Cryptodome/Util/__init__.py
new file mode 100644
index 0000000..1862b82
--- /dev/null
+++ b/frozen_deps/Cryptodome/Util/__init__.py
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Miscellaneous modules
+
+Contains useful modules that don't belong into any of the
+other Cryptodome.* subpackages.
+
+======================== =============================================
+Module Description
+======================== =============================================
+`Cryptodome.Util.number` Number-theoretic functions (primality testing, etc.)
+`Cryptodome.Util.Counter` Fast counter functions for CTR cipher modes.
+`Cryptodome.Util.RFC1751` Converts between 128-bit keys and human-readable
+ strings of words.
+`Cryptodome.Util.asn1` Minimal support for ASN.1 DER encoding
+`Cryptodome.Util.Padding` Set of functions for adding and removing padding.
+======================== =============================================
+
+:undocumented: _galois, _number_new, cpuid, py3compat, _raw_api
+"""
+
+__all__ = ['RFC1751', 'number', 'strxor', 'asn1', 'Counter', 'Padding']
+
diff --git a/frozen_deps/Cryptodome/Util/_cpu_features.py b/frozen_deps/Cryptodome/Util/_cpu_features.py
new file mode 100644
index 0000000..4794a02
--- /dev/null
+++ b/frozen_deps/Cryptodome/Util/_cpu_features.py
@@ -0,0 +1,46 @@
+# ===================================================================
+#
+# Copyright (c) 2018, Helder Eijs <[email protected]>
+# 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._raw_api import load_pycryptodome_raw_lib
+
+
+_raw_cpuid_lib = load_pycryptodome_raw_lib("Cryptodome.Util._cpuid_c",
+ """
+ int have_aes_ni(void);
+ int have_clmul(void);
+ """)
+
+
+def have_aes_ni():
+ return _raw_cpuid_lib.have_aes_ni()
+
+
+def have_clmul():
+ return _raw_cpuid_lib.have_clmul()
diff --git a/frozen_deps/Cryptodome/Util/_cpu_features.pyi b/frozen_deps/Cryptodome/Util/_cpu_features.pyi
new file mode 100644
index 0000000..10e669e
--- /dev/null
+++ b/frozen_deps/Cryptodome/Util/_cpu_features.pyi
@@ -0,0 +1,2 @@
+def have_aes_ni() -> int: ...
+def have_clmul() -> int: ...
diff --git a/frozen_deps/Cryptodome/Util/_cpuid_c.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Util/_cpuid_c.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..a555959
--- /dev/null
+++ b/frozen_deps/Cryptodome/Util/_cpuid_c.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Util/_file_system.py b/frozen_deps/Cryptodome/Util/_file_system.py
new file mode 100644
index 0000000..282f0dc
--- /dev/null
+++ b/frozen_deps/Cryptodome/Util/_file_system.py
@@ -0,0 +1,54 @@
+# ===================================================================
+#
+# Copyright (c) 2016, Legrandin <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+import os
+
+
+def pycryptodome_filename(dir_comps, filename):
+ """Return the complete file name for the module
+
+ dir_comps : list of string
+ The list of directory names in the PyCryptodome package.
+ The first element must be "Cryptodome".
+
+ filename : string
+ The filename (inclusing extension) in the target directory.
+ """
+
+ if dir_comps[0] != "Cryptodome":
+ raise ValueError("Only available for modules under 'Cryptodome'")
+
+ dir_comps = list(dir_comps[1:]) + [filename]
+
+ util_lib, _ = os.path.split(os.path.abspath(__file__))
+ root_lib = os.path.join(util_lib, "..")
+
+ return os.path.join(root_lib, *dir_comps)
+
diff --git a/frozen_deps/Cryptodome/Util/_file_system.pyi b/frozen_deps/Cryptodome/Util/_file_system.pyi
new file mode 100644
index 0000000..d54a126
--- /dev/null
+++ b/frozen_deps/Cryptodome/Util/_file_system.pyi
@@ -0,0 +1,4 @@
+from typing import List
+
+
+def pycryptodome_filename(dir_comps: List[str], filename: str) -> str: ... \ No newline at end of file
diff --git a/frozen_deps/Cryptodome/Util/_raw_api.py b/frozen_deps/Cryptodome/Util/_raw_api.py
new file mode 100644
index 0000000..9423738
--- /dev/null
+++ b/frozen_deps/Cryptodome/Util/_raw_api.py
@@ -0,0 +1,327 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ===================================================================
+
+import abc
+import sys
+from Cryptodome.Util.py3compat import byte_string
+from Cryptodome.Util._file_system import pycryptodome_filename
+
+#
+# List of file suffixes for Python extensions
+#
+if sys.version_info[0] < 3:
+
+ import imp
+ extension_suffixes = []
+ for ext, mod, typ in imp.get_suffixes():
+ if typ == imp.C_EXTENSION:
+ extension_suffixes.append(ext)
+
+else:
+
+ from importlib import machinery
+ extension_suffixes = machinery.EXTENSION_SUFFIXES
+
+# Which types with buffer interface we support (apart from byte strings)
+if sys.version_info[0] == 2 and sys.version_info[1] < 7:
+ _buffer_type = (bytearray)
+else:
+ _buffer_type = (bytearray, memoryview)
+
+
+class _VoidPointer(object):
+ @abc.abstractmethod
+ def get(self):
+ """Return the memory location we point to"""
+ return
+
+ @abc.abstractmethod
+ def address_of(self):
+ """Return a raw pointer to this pointer"""
+ return
+
+
+try:
+ if sys.version_info[0] == 2 and sys.version_info[1] < 7:
+ raise ImportError("CFFI is only supported with Python 2.7+")
+
+ # Starting from v2.18, pycparser (used by cffi for in-line ABI mode)
+ # stops working correctly when PYOPTIMIZE==2 or the parameter -OO is
+ # passed. In that case, we fall back to ctypes.
+ # Note that PyPy ships with an old version of pycparser so we can keep
+ # using cffi there.
+ # See https://github.com/Legrandin/pycryptodome/issues/228
+ if '__pypy__' not in sys.builtin_module_names and sys.flags.optimize == 2:
+ raise ImportError("CFFI with optimize=2 fails due to pycparser bug.")
+
+ from cffi import FFI
+
+ ffi = FFI()
+ null_pointer = ffi.NULL
+ uint8_t_type = ffi.typeof(ffi.new("const uint8_t*"))
+
+ _Array = ffi.new("uint8_t[1]").__class__.__bases__
+
+ def load_lib(name, cdecl):
+ """Load a shared library and return a handle to it.
+
+ @name, either an absolute path or the name of a library
+ in the system search path.
+
+ @cdecl, the C function declarations.
+ """
+
+ lib = ffi.dlopen(name)
+ ffi.cdef(cdecl)
+ return lib
+
+ def c_ulong(x):
+ """Convert a Python integer to unsigned long"""
+ return x
+
+ c_ulonglong = c_ulong
+ c_uint = c_ulong
+
+ def c_size_t(x):
+ """Convert a Python integer to size_t"""
+ return x
+
+ def create_string_buffer(init_or_size, size=None):
+ """Allocate the given amount of bytes (initially set to 0)"""
+
+ if isinstance(init_or_size, bytes):
+ size = max(len(init_or_size) + 1, size)
+ result = ffi.new("uint8_t[]", size)
+ result[:] = init_or_size
+ else:
+ if size:
+ raise ValueError("Size must be specified once only")
+ result = ffi.new("uint8_t[]", init_or_size)
+ return result
+
+ def get_c_string(c_string):
+ """Convert a C string into a Python byte sequence"""
+ return ffi.string(c_string)
+
+ def get_raw_buffer(buf):
+ """Convert a C buffer into a Python byte sequence"""
+ return ffi.buffer(buf)[:]
+
+ def c_uint8_ptr(data):
+ if isinstance(data, _buffer_type):
+ # This only works for cffi >= 1.7
+ return ffi.cast(uint8_t_type, ffi.from_buffer(data))
+ elif byte_string(data) or isinstance(data, _Array):
+ return data
+ else:
+ raise TypeError("Object type %s cannot be passed to C code" % type(data))
+
+ class VoidPointer_cffi(_VoidPointer):
+ """Model a newly allocated pointer to void"""
+
+ def __init__(self):
+ self._pp = ffi.new("void *[1]")
+
+ def get(self):
+ return self._pp[0]
+
+ def address_of(self):
+ return self._pp
+
+ def VoidPointer():
+ return VoidPointer_cffi()
+
+ backend = "cffi"
+
+except ImportError:
+
+ import ctypes
+ from ctypes import (CDLL, c_void_p, byref, c_ulong, c_ulonglong, c_size_t,
+ create_string_buffer, c_ubyte, c_uint)
+ from ctypes.util import find_library
+ from ctypes import Array as _Array
+
+ null_pointer = None
+ cached_architecture = []
+
+ def load_lib(name, cdecl):
+ if not cached_architecture:
+ # platform.architecture() creates a subprocess, so caching the
+ # result makes successive imports faster.
+ import platform
+ cached_architecture[:] = platform.architecture()
+ bits, linkage = cached_architecture
+ if "." not in name and not linkage.startswith("Win"):
+ full_name = find_library(name)
+ if full_name is None:
+ raise OSError("Cannot load library '%s'" % name)
+ name = full_name
+ return CDLL(name)
+
+ def get_c_string(c_string):
+ return c_string.value
+
+ def get_raw_buffer(buf):
+ return buf.raw
+
+ # ---- Get raw pointer ---
+
+ if sys.version_info[0] == 2 and sys.version_info[1] == 6:
+ # ctypes in 2.6 does not define c_ssize_t. Replacing it
+ # with c_size_t keeps the structure correctely laid out
+ _c_ssize_t = c_size_t
+ else:
+ _c_ssize_t = ctypes.c_ssize_t
+
+ _PyBUF_SIMPLE = 0
+ _PyObject_GetBuffer = ctypes.pythonapi.PyObject_GetBuffer
+ _PyBuffer_Release = ctypes.pythonapi.PyBuffer_Release
+ _py_object = ctypes.py_object
+ _c_ssize_p = ctypes.POINTER(_c_ssize_t)
+
+ # See Include/object.h for CPython
+ # and https://github.com/pallets/click/blob/master/click/_winconsole.py
+ class _Py_buffer(ctypes.Structure):
+ _fields_ = [
+ ('buf', c_void_p),
+ ('obj', ctypes.py_object),
+ ('len', _c_ssize_t),
+ ('itemsize', _c_ssize_t),
+ ('readonly', ctypes.c_int),
+ ('ndim', ctypes.c_int),
+ ('format', ctypes.c_char_p),
+ ('shape', _c_ssize_p),
+ ('strides', _c_ssize_p),
+ ('suboffsets', _c_ssize_p),
+ ('internal', c_void_p)
+ ]
+
+ # Extra field for CPython 2.6/2.7
+ if sys.version_info[0] == 2:
+ _fields_.insert(-1, ('smalltable', _c_ssize_t * 2))
+
+ def c_uint8_ptr(data):
+ if byte_string(data) or isinstance(data, _Array):
+ return data
+ elif isinstance(data, _buffer_type):
+ obj = _py_object(data)
+ buf = _Py_buffer()
+ _PyObject_GetBuffer(obj, byref(buf), _PyBUF_SIMPLE)
+ try:
+ buffer_type = c_ubyte * buf.len
+ return buffer_type.from_address(buf.buf)
+ finally:
+ _PyBuffer_Release(byref(buf))
+ else:
+ raise TypeError("Object type %s cannot be passed to C code" % type(data))
+
+ # ---
+
+ class VoidPointer_ctypes(_VoidPointer):
+ """Model a newly allocated pointer to void"""
+
+ def __init__(self):
+ self._p = c_void_p()
+
+ def get(self):
+ return self._p
+
+ def address_of(self):
+ return byref(self._p)
+
+ def VoidPointer():
+ return VoidPointer_ctypes()
+
+ backend = "ctypes"
+ del ctypes
+
+
+class SmartPointer(object):
+ """Class to hold a non-managed piece of memory"""
+
+ def __init__(self, raw_pointer, destructor):
+ self._raw_pointer = raw_pointer
+ self._destructor = destructor
+
+ def get(self):
+ return self._raw_pointer
+
+ def release(self):
+ rp, self._raw_pointer = self._raw_pointer, None
+ return rp
+
+ def __del__(self):
+ try:
+ if self._raw_pointer is not None:
+ self._destructor(self._raw_pointer)
+ self._raw_pointer = None
+ except AttributeError:
+ pass
+
+
+def load_pycryptodome_raw_lib(name, cdecl):
+ """Load a shared library and return a handle to it.
+
+ @name, the name of the library expressed as a PyCryptodome module,
+ for instance Cryptodome.Cipher._raw_cbc.
+
+ @cdecl, the C function declarations.
+ """
+
+ split = name.split(".")
+ dir_comps, basename = split[:-1], split[-1]
+ attempts = []
+ for ext in extension_suffixes:
+ try:
+ filename = basename + ext
+ return load_lib(pycryptodome_filename(dir_comps, filename),
+ cdecl)
+ except OSError as exp:
+ attempts.append("Trying '%s': %s" % (filename, str(exp)))
+ raise OSError("Cannot load native module '%s': %s" % (name, ", ".join(attempts)))
+
+
+if sys.version_info[:2] != (2, 6):
+
+ def is_buffer(x):
+ """Return True if object x supports the buffer interface"""
+ return isinstance(x, (bytes, bytearray, memoryview))
+
+ def is_writeable_buffer(x):
+ return (isinstance(x, bytearray) or
+ (isinstance(x, memoryview) and not x.readonly))
+
+else:
+
+ def is_buffer(x):
+ return isinstance(x, (bytes, bytearray))
+
+ def is_writeable_buffer(x):
+ return isinstance(x, bytearray)
diff --git a/frozen_deps/Cryptodome/Util/_raw_api.pyi b/frozen_deps/Cryptodome/Util/_raw_api.pyi
new file mode 100644
index 0000000..2bc5301
--- /dev/null
+++ b/frozen_deps/Cryptodome/Util/_raw_api.pyi
@@ -0,0 +1,27 @@
+from typing import Any, Optional, Union
+
+def load_lib(name: str, cdecl: str) -> Any : ...
+def c_ulong(x: int ) -> Any : ...
+def c_ulonglong(x: int ) -> Any : ...
+def c_size_t(x: int) -> Any : ...
+def create_string_buffer(init_or_size: Union[bytes,int], size: Optional[int]) -> Any : ...
+def get_c_string(c_string: Any) -> bytes : ...
+def get_raw_buffer(buf: Any) -> bytes : ...
+def c_uint8_ptr(data: Union[bytes, memoryview, bytearray]) -> Any : ...
+
+class VoidPointer(object):
+ def get(self) -> Any : ...
+ def address_of(self) -> Any : ...
+
+class SmartPointer(object):
+ def __init__(self, raw_pointer: Any, destructor: Any) -> None : ...
+ def get(self) -> Any : ...
+ def release(self) -> Any : ...
+
+backend : str
+null_pointer : Any
+ffi: Any
+
+def load_pycryptodome_raw_lib(name: str, cdecl: str) -> Any : ...
+def is_buffer(x: Any) -> bool : ...
+def is_writeable_buffer(x: Any) -> bool : ...
diff --git a/frozen_deps/Cryptodome/Util/_strxor.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Cryptodome/Util/_strxor.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..ea7566c
--- /dev/null
+++ b/frozen_deps/Cryptodome/Util/_strxor.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Cryptodome/Util/asn1.py b/frozen_deps/Cryptodome/Util/asn1.py
new file mode 100644
index 0000000..18e080c
--- /dev/null
+++ b/frozen_deps/Cryptodome/Util/asn1.py
@@ -0,0 +1,940 @@
+# -*- coding: ascii -*-
+#
+# Util/asn1.py : Minimal support for ASN.1 DER binary encoding.
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+import struct
+
+from Cryptodome.Util.py3compat import byte_string, b, bchr, bord
+
+from Cryptodome.Util.number import long_to_bytes, bytes_to_long
+
+__all__ = ['DerObject', 'DerInteger', 'DerOctetString', 'DerNull',
+ 'DerSequence', 'DerObjectId', 'DerBitString', 'DerSetOf']
+
+
+def _is_number(x, only_non_negative=False):
+ test = 0
+ try:
+ test = x + test
+ except TypeError:
+ return False
+ return not only_non_negative or x >= 0
+
+
+class BytesIO_EOF(object):
+ """This class differs from BytesIO in that a ValueError exception is
+ raised whenever EOF is reached."""
+
+ def __init__(self, initial_bytes):
+ self._buffer = initial_bytes
+ self._index = 0
+ self._bookmark = None
+
+ def set_bookmark(self):
+ self._bookmark = self._index
+
+ def data_since_bookmark(self):
+ assert self._bookmark is not None
+ return self._buffer[self._bookmark:self._index]
+
+ def remaining_data(self):
+ return len(self._buffer) - self._index
+
+ def read(self, length):
+ new_index = self._index + length
+ if new_index > len(self._buffer):
+ raise ValueError("Not enough data for DER decoding: expected %d bytes and found %d" % (new_index, len(self._buffer)))
+
+ result = self._buffer[self._index:new_index]
+ self._index = new_index
+ return result
+
+ def read_byte(self):
+ return bord(self.read(1)[0])
+
+
+class DerObject(object):
+ """Base class for defining a single DER object.
+
+ This class should never be directly instantiated.
+ """
+
+ def __init__(self, asn1Id=None, payload=b'', implicit=None,
+ constructed=False, explicit=None):
+ """Initialize the DER object according to a specific ASN.1 type.
+
+ :Parameters:
+ asn1Id : integer
+ The universal DER tag number for this object
+ (e.g. 0x10 for a SEQUENCE).
+ If None, the tag is not known yet.
+
+ payload : byte string
+ The initial payload of the object (that it,
+ the content octets).
+ If not specified, the payload is empty.
+
+ implicit : integer
+ The IMPLICIT tag number to use for the encoded object.
+ It overrides the universal tag *asn1Id*.
+
+ constructed : bool
+ True when the ASN.1 type is *constructed*.
+ False when it is *primitive*.
+
+ explicit : integer
+ The EXPLICIT tag number to use for the encoded object.
+ """
+
+ if asn1Id is None:
+ # The tag octet will be read in with ``decode``
+ self._tag_octet = None
+ return
+ asn1Id = self._convertTag(asn1Id)
+
+ self.payload = payload
+
+ # In a BER/DER identifier octet:
+ # * bits 4-0 contain the tag value
+ # * bit 5 is set if the type is 'constructed'
+ # and unset if 'primitive'
+ # * bits 7-6 depend on the encoding class
+ #
+ # Class | Bit 7, Bit 6
+ # ----------------------------------
+ # universal | 0 0
+ # application | 0 1
+ # context-spec | 1 0 (default for IMPLICIT/EXPLICIT)
+ # private | 1 1
+ #
+ if None not in (explicit, implicit):
+ raise ValueError("Explicit and implicit tags are"
+ " mutually exclusive")
+
+ if implicit is not None:
+ self._tag_octet = 0x80 | 0x20 * constructed | self._convertTag(implicit)
+ return
+
+ if explicit is not None:
+ self._tag_octet = 0xA0 | self._convertTag(explicit)
+ self._inner_tag_octet = 0x20 * constructed | asn1Id
+ return
+
+ self._tag_octet = 0x20 * constructed | asn1Id
+
+ def _convertTag(self, tag):
+ """Check if *tag* is a real DER tag.
+ Convert it from a character to number if necessary.
+ """
+ if not _is_number(tag):
+ if len(tag) == 1:
+ tag = bord(tag[0])
+ # Ensure that tag is a low tag
+ if not (_is_number(tag) and 0 <= tag < 0x1F):
+ raise ValueError("Wrong DER tag")
+ return tag
+
+ @staticmethod
+ def _definite_form(length):
+ """Build length octets according to BER/DER
+ definite form.
+ """
+ if length > 127:
+ encoding = long_to_bytes(length)
+ return bchr(len(encoding) + 128) + encoding
+ return bchr(length)
+
+ def encode(self):
+ """Return this DER element, fully encoded as a binary byte string."""
+
+ # Concatenate identifier octets, length octets,
+ # and contents octets
+
+ output_payload = self.payload
+
+ # In case of an EXTERNAL tag, first encode the inner
+ # element.
+ if hasattr(self, "_inner_tag_octet"):
+ output_payload = (bchr(self._inner_tag_octet) +
+ self._definite_form(len(self.payload)) +
+ self.payload)
+
+ return (bchr(self._tag_octet) +
+ self._definite_form(len(output_payload)) +
+ output_payload)
+
+ def _decodeLen(self, s):
+ """Decode DER length octets from a file."""
+
+ length = s.read_byte()
+
+ if length > 127:
+ encoded_length = s.read(length & 0x7F)
+ if bord(encoded_length[0]) == 0:
+ raise ValueError("Invalid DER: length has leading zero")
+ length = bytes_to_long(encoded_length)
+ if length <= 127:
+ raise ValueError("Invalid DER: length in long form but smaller than 128")
+
+ return length
+
+ def decode(self, der_encoded, strict=False):
+ """Decode a complete DER element, and re-initializes this
+ object with it.
+
+ Args:
+ der_encoded (byte string): A complete DER element.
+
+ Raises:
+ ValueError: in case of parsing errors.
+ """
+
+ if not byte_string(der_encoded):
+ raise ValueError("Input is not a byte string")
+
+ s = BytesIO_EOF(der_encoded)
+ self._decodeFromStream(s, strict)
+
+ # There shouldn't be other bytes left
+ if s.remaining_data() > 0:
+ raise ValueError("Unexpected extra data after the DER structure")
+
+ return self
+
+ def _decodeFromStream(self, s, strict):
+ """Decode a complete DER element from a file."""
+
+ idOctet = s.read_byte()
+ if self._tag_octet is not None:
+ if idOctet != self._tag_octet:
+ raise ValueError("Unexpected DER tag")
+ else:
+ self._tag_octet = idOctet
+ length = self._decodeLen(s)
+ self.payload = s.read(length)
+
+ # In case of an EXTERNAL tag, further decode the inner
+ # element.
+ if hasattr(self, "_inner_tag_octet"):
+ p = BytesIO_EOF(self.payload)
+ inner_octet = p.read_byte()
+ if inner_octet != self._inner_tag_octet:
+ raise ValueError("Unexpected internal DER tag")
+ length = self._decodeLen(p)
+ self.payload = p.read(length)
+
+ # There shouldn't be other bytes left
+ if p.remaining_data() > 0:
+ raise ValueError("Unexpected extra data after the DER structure")
+
+
+class DerInteger(DerObject):
+ """Class to model a DER INTEGER.
+
+ An example of encoding is::
+
+ >>> from Cryptodome.Util.asn1 import DerInteger
+ >>> from binascii import hexlify, unhexlify
+ >>> int_der = DerInteger(9)
+ >>> print hexlify(int_der.encode())
+
+ which will show ``020109``, the DER encoding of 9.
+
+ And for decoding::
+
+ >>> s = unhexlify(b'020109')
+ >>> try:
+ >>> int_der = DerInteger()
+ >>> int_der.decode(s)
+ >>> print int_der.value
+ >>> except ValueError:
+ >>> print "Not a valid DER INTEGER"
+
+ the output will be ``9``.
+
+ :ivar value: The integer value
+ :vartype value: integer
+ """
+
+ def __init__(self, value=0, implicit=None, explicit=None):
+ """Initialize the DER object as an INTEGER.
+
+ :Parameters:
+ value : integer
+ The value of the integer.
+
+ implicit : integer
+ The IMPLICIT tag to use for the encoded object.
+ It overrides the universal tag for INTEGER (2).
+ """
+
+ DerObject.__init__(self, 0x02, b'', implicit,
+ False, explicit)
+ self.value = value # The integer value
+
+ def encode(self):
+ """Return the DER INTEGER, fully encoded as a
+ binary string."""
+
+ number = self.value
+ self.payload = b''
+ while True:
+ self.payload = bchr(int(number & 255)) + self.payload
+ if 128 <= number <= 255:
+ self.payload = bchr(0x00) + self.payload
+ if -128 <= number <= 255:
+ break
+ number >>= 8
+ return DerObject.encode(self)
+
+ def decode(self, der_encoded, strict=False):
+ """Decode a complete DER INTEGER DER, and re-initializes this
+ object with it.
+
+ Args:
+ der_encoded (byte string): A complete INTEGER DER element.
+
+ Raises:
+ ValueError: in case of parsing errors.
+ """
+
+ return DerObject.decode(self, der_encoded, strict=strict)
+
+ def _decodeFromStream(self, s, strict):
+ """Decode a complete DER INTEGER from a file."""
+
+ # Fill up self.payload
+ DerObject._decodeFromStream(self, s, strict)
+
+ if strict:
+ if len(self.payload) == 0:
+ raise ValueError("Invalid encoding for DER INTEGER: empty payload")
+ if len(self.payload) >= 2 and struct.unpack('>H', self.payload[:2])[0] < 0x80:
+ raise ValueError("Invalid encoding for DER INTEGER: leading zero")
+
+ # Derive self.value from self.payload
+ self.value = 0
+ bits = 1
+ for i in self.payload:
+ self.value *= 256
+ self.value += bord(i)
+ bits <<= 8
+ if self.payload and bord(self.payload[0]) & 0x80:
+ self.value -= bits
+
+
+class DerSequence(DerObject):
+ """Class to model a DER SEQUENCE.
+
+ This object behaves like a dynamic Python sequence.
+
+ Sub-elements that are INTEGERs behave like Python integers.
+
+ Any other sub-element is a binary string encoded as a complete DER
+ sub-element (TLV).
+
+ An example of encoding is:
+
+ >>> from Cryptodome.Util.asn1 import DerSequence, DerInteger
+ >>> from binascii import hexlify, unhexlify
+ >>> obj_der = unhexlify('070102')
+ >>> seq_der = DerSequence([4])
+ >>> seq_der.append(9)
+ >>> seq_der.append(obj_der.encode())
+ >>> print hexlify(seq_der.encode())
+
+ which will show ``3009020104020109070102``, the DER encoding of the
+ sequence containing ``4``, ``9``, and the object with payload ``02``.
+
+ For decoding:
+
+ >>> s = unhexlify(b'3009020104020109070102')
+ >>> try:
+ >>> seq_der = DerSequence()
+ >>> seq_der.decode(s)
+ >>> print len(seq_der)
+ >>> print seq_der[0]
+ >>> print seq_der[:]
+ >>> except ValueError:
+ >>> print "Not a valid DER SEQUENCE"
+
+ the output will be::
+
+ 3
+ 4
+ [4, 9, b'\x07\x01\x02']
+
+ """
+
+ def __init__(self, startSeq=None, implicit=None):
+ """Initialize the DER object as a SEQUENCE.
+
+ :Parameters:
+ startSeq : Python sequence
+ A sequence whose element are either integers or
+ other DER objects.
+
+ implicit : integer
+ The IMPLICIT tag to use for the encoded object.
+ It overrides the universal tag for SEQUENCE (16).
+ """
+
+ DerObject.__init__(self, 0x10, b'', implicit, True)
+ if startSeq is None:
+ self._seq = []
+ else:
+ self._seq = startSeq
+
+ # A few methods to make it behave like a python sequence
+
+ def __delitem__(self, n):
+ del self._seq[n]
+
+ def __getitem__(self, n):
+ return self._seq[n]
+
+ def __setitem__(self, key, value):
+ self._seq[key] = value
+
+ def __setslice__(self, i, j, sequence):
+ self._seq[i:j] = sequence
+
+ def __delslice__(self, i, j):
+ del self._seq[i:j]
+
+ def __getslice__(self, i, j):
+ return self._seq[max(0, i):max(0, j)]
+
+ def __len__(self):
+ return len(self._seq)
+
+ def __iadd__(self, item):
+ self._seq.append(item)
+ return self
+
+ def append(self, item):
+ self._seq.append(item)
+ return self
+
+ def hasInts(self, only_non_negative=True):
+ """Return the number of items in this sequence that are
+ integers.
+
+ Args:
+ only_non_negative (boolean):
+ If ``True``, negative integers are not counted in.
+ """
+
+ items = [x for x in self._seq if _is_number(x, only_non_negative)]
+ return len(items)
+
+ def hasOnlyInts(self, only_non_negative=True):
+ """Return ``True`` if all items in this sequence are integers
+ or non-negative integers.
+
+ This function returns False is the sequence is empty,
+ or at least one member is not an integer.
+
+ Args:
+ only_non_negative (boolean):
+ If ``True``, the presence of negative integers
+ causes the method to return ``False``."""
+ return self._seq and self.hasInts(only_non_negative) == len(self._seq)
+
+ def encode(self):
+ """Return this DER SEQUENCE, fully encoded as a
+ binary string.
+
+ Raises:
+ ValueError: if some elements in the sequence are neither integers
+ nor byte strings.
+ """
+ self.payload = b''
+ for item in self._seq:
+ if byte_string(item):
+ self.payload += item
+ elif _is_number(item):
+ self.payload += DerInteger(item).encode()
+ else:
+ self.payload += item.encode()
+ return DerObject.encode(self)
+
+ def decode(self, der_encoded, strict=False, nr_elements=None, only_ints_expected=False):
+ """Decode a complete DER SEQUENCE, and re-initializes this
+ object with it.
+
+ Args:
+ der_encoded (byte string):
+ A complete SEQUENCE DER element.
+ nr_elements (None or integer or list of integers):
+ The number of members the SEQUENCE can have
+ only_ints_expected (boolean):
+ Whether the SEQUENCE is expected to contain only integers.
+ strict (boolean):
+ Whether decoding must check for strict DER compliancy.
+
+ Raises:
+ ValueError: in case of parsing errors.
+
+ DER INTEGERs are decoded into Python integers. Any other DER
+ element is not decoded. Its validity is not checked.
+ """
+
+ self._nr_elements = nr_elements
+ result = DerObject.decode(self, der_encoded, strict=strict)
+
+ if only_ints_expected and not self.hasOnlyInts():
+ raise ValueError("Some members are not INTEGERs")
+
+ return result
+
+ def _decodeFromStream(self, s, strict):
+ """Decode a complete DER SEQUENCE from a file."""
+
+ self._seq = []
+
+ # Fill up self.payload
+ DerObject._decodeFromStream(self, s, strict)
+
+ # Add one item at a time to self.seq, by scanning self.payload
+ p = BytesIO_EOF(self.payload)
+ while p.remaining_data() > 0:
+ p.set_bookmark()
+
+ der = DerObject()
+ der._decodeFromStream(p, strict)
+
+ # Parse INTEGERs differently
+ if der._tag_octet != 0x02:
+ self._seq.append(p.data_since_bookmark())
+ else:
+ derInt = DerInteger()
+ #import pdb; pdb.set_trace()
+ data = p.data_since_bookmark()
+ derInt.decode(data, strict=strict)
+ self._seq.append(derInt.value)
+
+ ok = True
+ if self._nr_elements is not None:
+ try:
+ ok = len(self._seq) in self._nr_elements
+ except TypeError:
+ ok = len(self._seq) == self._nr_elements
+
+ if not ok:
+ raise ValueError("Unexpected number of members (%d)"
+ " in the sequence" % len(self._seq))
+
+
+class DerOctetString(DerObject):
+ """Class to model a DER OCTET STRING.
+
+ An example of encoding is:
+
+ >>> from Cryptodome.Util.asn1 import DerOctetString
+ >>> from binascii import hexlify, unhexlify
+ >>> os_der = DerOctetString(b'\\xaa')
+ >>> os_der.payload += b'\\xbb'
+ >>> print hexlify(os_der.encode())
+
+ which will show ``0402aabb``, the DER encoding for the byte string
+ ``b'\\xAA\\xBB'``.
+
+ For decoding:
+
+ >>> s = unhexlify(b'0402aabb')
+ >>> try:
+ >>> os_der = DerOctetString()
+ >>> os_der.decode(s)
+ >>> print hexlify(os_der.payload)
+ >>> except ValueError:
+ >>> print "Not a valid DER OCTET STRING"
+
+ the output will be ``aabb``.
+
+ :ivar payload: The content of the string
+ :vartype payload: byte string
+ """
+
+ def __init__(self, value=b'', implicit=None):
+ """Initialize the DER object as an OCTET STRING.
+
+ :Parameters:
+ value : byte string
+ The initial payload of the object.
+ If not specified, the payload is empty.
+
+ implicit : integer
+ The IMPLICIT tag to use for the encoded object.
+ It overrides the universal tag for OCTET STRING (4).
+ """
+ DerObject.__init__(self, 0x04, value, implicit, False)
+
+
+class DerNull(DerObject):
+ """Class to model a DER NULL element."""
+
+ def __init__(self):
+ """Initialize the DER object as a NULL."""
+
+ DerObject.__init__(self, 0x05, b'', None, False)
+
+
+class DerObjectId(DerObject):
+ """Class to model a DER OBJECT ID.
+
+ An example of encoding is:
+
+ >>> from Cryptodome.Util.asn1 import DerObjectId
+ >>> from binascii import hexlify, unhexlify
+ >>> oid_der = DerObjectId("1.2")
+ >>> oid_der.value += ".840.113549.1.1.1"
+ >>> print hexlify(oid_der.encode())
+
+ which will show ``06092a864886f70d010101``, the DER encoding for the
+ RSA Object Identifier ``1.2.840.113549.1.1.1``.
+
+ For decoding:
+
+ >>> s = unhexlify(b'06092a864886f70d010101')
+ >>> try:
+ >>> oid_der = DerObjectId()
+ >>> oid_der.decode(s)
+ >>> print oid_der.value
+ >>> except ValueError:
+ >>> print "Not a valid DER OBJECT ID"
+
+ the output will be ``1.2.840.113549.1.1.1``.
+
+ :ivar value: The Object ID (OID), a dot separated list of integers
+ :vartype value: string
+ """
+
+ def __init__(self, value='', implicit=None, explicit=None):
+ """Initialize the DER object as an OBJECT ID.
+
+ :Parameters:
+ value : string
+ The initial Object Identifier (e.g. "1.2.0.0.6.2").
+ implicit : integer
+ The IMPLICIT tag to use for the encoded object.
+ It overrides the universal tag for OBJECT ID (6).
+ explicit : integer
+ The EXPLICIT tag to use for the encoded object.
+ """
+ DerObject.__init__(self, 0x06, b'', implicit, False, explicit)
+ self.value = value
+
+ def encode(self):
+ """Return the DER OBJECT ID, fully encoded as a
+ binary string."""
+
+ comps = [int(x) for x in self.value.split(".")]
+ if len(comps) < 2:
+ raise ValueError("Not a valid Object Identifier string")
+ self.payload = bchr(40*comps[0]+comps[1])
+ for v in comps[2:]:
+ if v == 0:
+ enc = [0]
+ else:
+ enc = []
+ while v:
+ enc.insert(0, (v & 0x7F) | 0x80)
+ v >>= 7
+ enc[-1] &= 0x7F
+ self.payload += b''.join([bchr(x) for x in enc])
+ return DerObject.encode(self)
+
+ def decode(self, der_encoded, strict=False):
+ """Decode a complete DER OBJECT ID, and re-initializes this
+ object with it.
+
+ Args:
+ der_encoded (byte string):
+ A complete DER OBJECT ID.
+ strict (boolean):
+ Whether decoding must check for strict DER compliancy.
+
+ Raises:
+ ValueError: in case of parsing errors.
+ """
+
+ return DerObject.decode(self, der_encoded, strict)
+
+ def _decodeFromStream(self, s, strict):
+ """Decode a complete DER OBJECT ID from a file."""
+
+ # Fill up self.payload
+ DerObject._decodeFromStream(self, s, strict)
+
+ # Derive self.value from self.payload
+ p = BytesIO_EOF(self.payload)
+ comps = [str(x) for x in divmod(p.read_byte(), 40)]
+ v = 0
+ while p.remaining_data():
+ c = p.read_byte()
+ v = v*128 + (c & 0x7F)
+ if not (c & 0x80):
+ comps.append(str(v))
+ v = 0
+ self.value = '.'.join(comps)
+
+
+class DerBitString(DerObject):
+ """Class to model a DER BIT STRING.
+
+ An example of encoding is:
+
+ >>> from Cryptodome.Util.asn1 import DerBitString
+ >>> from binascii import hexlify, unhexlify
+ >>> bs_der = DerBitString(b'\\xaa')
+ >>> bs_der.value += b'\\xbb'
+ >>> print hexlify(bs_der.encode())
+
+ which will show ``040300aabb``, the DER encoding for the bit string
+ ``b'\\xAA\\xBB'``.
+
+ For decoding:
+
+ >>> s = unhexlify(b'040300aabb')
+ >>> try:
+ >>> bs_der = DerBitString()
+ >>> bs_der.decode(s)
+ >>> print hexlify(bs_der.value)
+ >>> except ValueError:
+ >>> print "Not a valid DER BIT STRING"
+
+ the output will be ``aabb``.
+
+ :ivar value: The content of the string
+ :vartype value: byte string
+ """
+
+ def __init__(self, value=b'', implicit=None, explicit=None):
+ """Initialize the DER object as a BIT STRING.
+
+ :Parameters:
+ value : byte string or DER object
+ The initial, packed bit string.
+ If not specified, the bit string is empty.
+ implicit : integer
+ The IMPLICIT tag to use for the encoded object.
+ It overrides the universal tag for OCTET STRING (3).
+ explicit : integer
+ The EXPLICIT tag to use for the encoded object.
+ """
+ DerObject.__init__(self, 0x03, b'', implicit, False, explicit)
+
+ # The bitstring value (packed)
+ if isinstance(value, DerObject):
+ self.value = value.encode()
+ else:
+ self.value = value
+
+ def encode(self):
+ """Return the DER BIT STRING, fully encoded as a
+ binary string."""
+
+ # Add padding count byte
+ self.payload = b'\x00' + self.value
+ return DerObject.encode(self)
+
+ def decode(self, der_encoded, strict=False):
+ """Decode a complete DER BIT STRING, and re-initializes this
+ object with it.
+
+ Args:
+ der_encoded (byte string): a complete DER BIT STRING.
+ strict (boolean):
+ Whether decoding must check for strict DER compliancy.
+
+ Raises:
+ ValueError: in case of parsing errors.
+ """
+
+ return DerObject.decode(self, der_encoded, strict)
+
+ def _decodeFromStream(self, s, strict):
+ """Decode a complete DER BIT STRING DER from a file."""
+
+ # Fill-up self.payload
+ DerObject._decodeFromStream(self, s, strict)
+
+ if self.payload and bord(self.payload[0]) != 0:
+ raise ValueError("Not a valid BIT STRING")
+
+ # Fill-up self.value
+ self.value = b''
+ # Remove padding count byte
+ if self.payload:
+ self.value = self.payload[1:]
+
+
+class DerSetOf(DerObject):
+ """Class to model a DER SET OF.
+
+ An example of encoding is:
+
+ >>> from Cryptodome.Util.asn1 import DerBitString
+ >>> from binascii import hexlify, unhexlify
+ >>> so_der = DerSetOf([4,5])
+ >>> so_der.add(6)
+ >>> print hexlify(so_der.encode())
+
+ which will show ``3109020104020105020106``, the DER encoding
+ of a SET OF with items 4,5, and 6.
+
+ For decoding:
+
+ >>> s = unhexlify(b'3109020104020105020106')
+ >>> try:
+ >>> so_der = DerSetOf()
+ >>> so_der.decode(s)
+ >>> print [x for x in so_der]
+ >>> except ValueError:
+ >>> print "Not a valid DER SET OF"
+
+ the output will be ``[4, 5, 6]``.
+ """
+
+ def __init__(self, startSet=None, implicit=None):
+ """Initialize the DER object as a SET OF.
+
+ :Parameters:
+ startSet : container
+ The initial set of integers or DER encoded objects.
+ implicit : integer
+ The IMPLICIT tag to use for the encoded object.
+ It overrides the universal tag for SET OF (17).
+ """
+ DerObject.__init__(self, 0x11, b'', implicit, True)
+ self._seq = []
+
+ # All elements must be of the same type (and therefore have the
+ # same leading octet)
+ self._elemOctet = None
+
+ if startSet:
+ for e in startSet:
+ self.add(e)
+
+ def __getitem__(self, n):
+ return self._seq[n]
+
+ def __iter__(self):
+ return iter(self._seq)
+
+ def __len__(self):
+ return len(self._seq)
+
+ def add(self, elem):
+ """Add an element to the set.
+
+ Args:
+ elem (byte string or integer):
+ An element of the same type of objects already in the set.
+ It can be an integer or a DER encoded object.
+ """
+
+ if _is_number(elem):
+ eo = 0x02
+ elif isinstance(elem, DerObject):
+ eo = self._tag_octet
+ else:
+ eo = bord(elem[0])
+
+ if self._elemOctet != eo:
+ if self._elemOctet is not None:
+ raise ValueError("New element does not belong to the set")
+ self._elemOctet = eo
+
+ if elem not in self._seq:
+ self._seq.append(elem)
+
+ def decode(self, der_encoded, strict=False):
+ """Decode a complete SET OF DER element, and re-initializes this
+ object with it.
+
+ DER INTEGERs are decoded into Python integers. Any other DER
+ element is left undecoded; its validity is not checked.
+
+ Args:
+ der_encoded (byte string): a complete DER BIT SET OF.
+ strict (boolean):
+ Whether decoding must check for strict DER compliancy.
+
+ Raises:
+ ValueError: in case of parsing errors.
+ """
+
+ return DerObject.decode(self, der_encoded, strict)
+
+ def _decodeFromStream(self, s, strict):
+ """Decode a complete DER SET OF from a file."""
+
+ self._seq = []
+
+ # Fill up self.payload
+ DerObject._decodeFromStream(self, s, strict)
+
+ # Add one item at a time to self.seq, by scanning self.payload
+ p = BytesIO_EOF(self.payload)
+ setIdOctet = -1
+ while p.remaining_data() > 0:
+ p.set_bookmark()
+
+ der = DerObject()
+ der._decodeFromStream(p, strict)
+
+ # Verify that all members are of the same type
+ if setIdOctet < 0:
+ setIdOctet = der._tag_octet
+ else:
+ if setIdOctet != der._tag_octet:
+ raise ValueError("Not all elements are of the same DER type")
+
+ # Parse INTEGERs differently
+ if setIdOctet != 0x02:
+ self._seq.append(p.data_since_bookmark())
+ else:
+ derInt = DerInteger()
+ derInt.decode(p.data_since_bookmark(), strict)
+ self._seq.append(derInt.value)
+ # end
+
+ def encode(self):
+ """Return this SET OF DER element, fully encoded as a
+ binary string.
+ """
+
+ # Elements in the set must be ordered in lexicographic order
+ ordered = []
+ for item in self._seq:
+ if _is_number(item):
+ bys = DerInteger(item).encode()
+ elif isinstance(item, DerObject):
+ bys = item.encode()
+ else:
+ bys = item
+ ordered.append(bys)
+ ordered.sort()
+ self.payload = b''.join(ordered)
+ return DerObject.encode(self)
diff --git a/frozen_deps/Cryptodome/Util/asn1.pyi b/frozen_deps/Cryptodome/Util/asn1.pyi
new file mode 100644
index 0000000..dac023b
--- /dev/null
+++ b/frozen_deps/Cryptodome/Util/asn1.pyi
@@ -0,0 +1,74 @@
+from typing import Optional, Sequence, Union, Set, Iterable
+
+__all__ = ['DerObject', 'DerInteger', 'DerOctetString', 'DerNull',
+ 'DerSequence', 'DerObjectId', 'DerBitString', 'DerSetOf']
+
+# TODO: Make the encoded DerObjects their own type, so that DerSequence and
+# DerSetOf can check their contents better
+
+class BytesIO_EOF:
+ def __init__(self, initial_bytes: bytes) -> None: ...
+ def set_bookmark(self) -> None: ...
+ def data_since_bookmark(self) -> bytes: ...
+ def remaining_data(self) -> int: ...
+ def read(self, length: int) -> bytes: ...
+ def read_byte(self) -> bytes: ...
+
+class DerObject:
+ payload: bytes
+ def __init__(self, asn1Id: Optional[int]=None, payload: Optional[bytes]=..., implicit: Optional[int]=None,
+ constructed: Optional[bool]=False, explicit: Optional[int]=None) -> None: ...
+ def encode(self) -> bytes: ...
+ def decode(self, der_encoded: bytes, strict: Optional[bool]=False) -> DerObject: ...
+
+class DerInteger(DerObject):
+ value: int
+ def __init__(self, value: Optional[int]= 0, implicit: Optional[int]=None, explicit: Optional[int]=None) -> None: ...
+ def encode(self) -> bytes: ...
+ def decode(self, der_encoded: bytes, strict: Optional[bool]=False) -> DerInteger: ...
+
+class DerSequence(DerObject):
+ def __init__(self, startSeq: Optional[Sequence[Union[int, DerInteger, DerObject]]]=None, implicit: Optional[int]=None) -> None: ...
+ def __delitem__(self, n: int) -> None: ...
+ def __getitem__(self, n: int) -> None: ...
+ def __setitem__(self, key: int, value: DerObject) -> None: ...
+ def __setslice__(self, i: int, j: int, sequence: Sequence) -> None: ...
+ def __delslice__(self, i: int, j: int) -> None: ...
+ def __getslice__(self, i: int, j: int) -> DerSequence: ...
+ def __len__(self) -> int: ...
+ def __iadd__(self, item: DerObject) -> DerSequence: ...
+ def append(self, item: DerObject) -> DerSequence: ...
+ def hasInts(self, only_non_negative: Optional[bool]=True) -> int: ...
+ def hasOnlyInts(self, only_non_negative: Optional[bool]=True) -> bool: ...
+ def encode(self) -> bytes: ...
+ def decode(self, der_encoded: bytes, strict: Optional[bool]=False, nr_elements: Optional[int]=None, only_ints_expected: Optional[bool]=False) -> DerSequence: ...
+
+class DerOctetString(DerObject):
+ payload: bytes
+ def __init__(self, value: Optional[bytes]=..., implicit: Optional[int]=None) -> None: ...
+
+class DerNull(DerObject):
+ def __init__(self) -> None: ...
+
+class DerObjectId(DerObject):
+ value: str
+ def __init__(self, value: Optional[str]=..., implicit: Optional[int]=None, explicit: Optional[int]=None) -> None: ...
+ def encode(self) -> bytes: ...
+ def decode(self, der_encoded: bytes, strict: Optional[bool]=False) -> DerObjectId: ...
+
+class DerBitString(DerObject):
+ value: bytes
+ def __init__(self, value: Optional[bytes]=..., implicit: Optional[int]=None, explicit: Optional[int]=None) -> None: ...
+ def encode(self) -> bytes: ...
+ def decode(self, der_encoded: bytes, strict: Optional[bool]=False) -> DerBitString: ...
+
+DerSetElement = Union[bytes, int]
+
+class DerSetOf(DerObject):
+ def __init__(self, startSet: Optional[Set[DerSetElement]]=None, implicit: Optional[int]=None) -> None: ...
+ def __getitem__(self, n: int) -> DerSetElement: ...
+ def __iter__(self) -> Iterable: ...
+ def __len__(self) -> int: ...
+ def add(self, elem: DerSetElement) -> None: ...
+ def decode(self, der_encoded: bytes, strict: Optional[bool]=False) -> DerObject: ...
+ def encode(self) -> bytes: ...
diff --git a/frozen_deps/Cryptodome/Util/number.py b/frozen_deps/Cryptodome/Util/number.py
new file mode 100644
index 0000000..0367fdc
--- /dev/null
+++ b/frozen_deps/Cryptodome/Util/number.py
@@ -0,0 +1,1469 @@
+#
+# number.py : Number-theoretic functions
+#
+# Part of the Python Cryptography Toolkit
+#
+# Written by Andrew M. Kuchling, Barry A. Warsaw, and others
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+#
+
+import math
+import sys
+import struct
+from Cryptodome import Random
+from Cryptodome.Util.py3compat import _memoryview, iter_range
+
+# Backward compatibility
+_fastmath = None
+
+
+def ceil_div(n, d):
+ """Return ceil(n/d), that is, the smallest integer r such that r*d >= n"""
+
+ if d == 0:
+ raise ZeroDivisionError()
+ if (n < 0) or (d < 0):
+ raise ValueError("Non positive values")
+ r, q = divmod(n, d)
+ if (n != 0) and (q != 0):
+ r += 1
+ return r
+
+
+def size (N):
+ """Returns the size of the number N in bits."""
+
+ if N < 0:
+ raise ValueError("Size in bits only avialable for non-negative numbers")
+
+ bits = 0
+ while N >> bits:
+ bits += 1
+ return bits
+
+
+def getRandomInteger(N, randfunc=None):
+ """Return a random number at most N bits long.
+
+ If :data:`randfunc` is omitted, then :meth:`Random.get_random_bytes` is used.
+
+ .. deprecated:: 3.0
+ This function is for internal use only and may be renamed or removed in
+ the future. Use :func:`Cryptodome.Random.random.getrandbits` instead.
+ """
+
+ if randfunc is None:
+ randfunc = Random.get_random_bytes
+
+ S = randfunc(N>>3)
+ odd_bits = N % 8
+ if odd_bits != 0:
+ rand_bits = ord(randfunc(1)) >> (8-odd_bits)
+ S = struct.pack('B', rand_bits) + S
+ value = bytes_to_long(S)
+ return value
+
+def getRandomRange(a, b, randfunc=None):
+ """Return a random number *n* so that *a <= n < b*.
+
+ If :data:`randfunc` is omitted, then :meth:`Random.get_random_bytes` is used.
+
+ .. deprecated:: 3.0
+ This function is for internal use only and may be renamed or removed in
+ the future. Use :func:`Cryptodome.Random.random.randrange` instead.
+ """
+
+ range_ = b - a - 1
+ bits = size(range_)
+ value = getRandomInteger(bits, randfunc)
+ while value > range_:
+ value = getRandomInteger(bits, randfunc)
+ return a + value
+
+def getRandomNBitInteger(N, randfunc=None):
+ """Return a random number with exactly N-bits,
+ i.e. a random number between 2**(N-1) and (2**N)-1.
+
+ If :data:`randfunc` is omitted, then :meth:`Random.get_random_bytes` is used.
+
+ .. deprecated:: 3.0
+ This function is for internal use only and may be renamed or removed in
+ the future.
+ """
+
+ value = getRandomInteger (N-1, randfunc)
+ value |= 2 ** (N-1) # Ensure high bit is set
+ assert size(value) >= N
+ return value
+
+def GCD(x,y):
+ """Greatest Common Denominator of :data:`x` and :data:`y`.
+ """
+
+ x = abs(x) ; y = abs(y)
+ while x > 0:
+ x, y = y % x, x
+ return y
+
+def inverse(u, v):
+ """The inverse of :data:`u` *mod* :data:`v`."""
+
+ u3, v3 = u, v
+ u1, v1 = 1, 0
+ while v3 > 0:
+ q = u3 // v3
+ u1, v1 = v1, u1 - v1*q
+ u3, v3 = v3, u3 - v3*q
+ while u1<0:
+ u1 = u1 + v
+ return u1
+
+# Given a number of bits to generate and a random generation function,
+# find a prime number of the appropriate size.
+
+def getPrime(N, randfunc=None):
+ """Return a random N-bit prime number.
+
+ If randfunc is omitted, then :meth:`Random.get_random_bytes` is used.
+ """
+ if randfunc is None:
+ randfunc = Random.get_random_bytes
+
+ number=getRandomNBitInteger(N, randfunc) | 1
+ while (not isPrime(number, randfunc=randfunc)):
+ number=number+2
+ return number
+
+
+def _rabinMillerTest(n, rounds, randfunc=None):
+ """_rabinMillerTest(n:long, rounds:int, randfunc:callable):int
+ Tests if n is prime.
+ Returns 0 when n is definitely composite.
+ Returns 1 when n is probably prime.
+ Returns 2 when n is definitely prime.
+
+ If randfunc is omitted, then Random.new().read is used.
+
+ This function is for internal use only and may be renamed or removed in
+ the future.
+ """
+ # check special cases (n==2, n even, n < 2)
+ if n < 3 or (n & 1) == 0:
+ return n == 2
+ # n might be very large so it might be beneficial to precalculate n-1
+ n_1 = n - 1
+ # determine m and b so that 2**b * m = n - 1 and b maximal
+ b = 0
+ m = n_1
+ while (m & 1) == 0:
+ b += 1
+ m >>= 1
+
+ tested = []
+ # we need to do at most n-2 rounds.
+ for i in iter_range (min (rounds, n-2)):
+ # randomly choose a < n and make sure it hasn't been tested yet
+ a = getRandomRange (2, n, randfunc)
+ while a in tested:
+ a = getRandomRange (2, n, randfunc)
+ tested.append (a)
+ # do the rabin-miller test
+ z = pow (a, m, n) # (a**m) % n
+ if z == 1 or z == n_1:
+ continue
+ composite = 1
+ for r in iter_range(b):
+ z = (z * z) % n
+ if z == 1:
+ return 0
+ elif z == n_1:
+ composite = 0
+ break
+ if composite:
+ return 0
+ return 1
+
+def getStrongPrime(N, e=0, false_positive_prob=1e-6, randfunc=None):
+ r"""
+ Return a random strong *N*-bit prime number.
+ In this context, *p* is a strong prime if *p-1* and *p+1* have at
+ least one large prime factor.
+
+ Args:
+ N (integer): the exact length of the strong prime.
+ It must be a multiple of 128 and > 512.
+ e (integer): if provided, the returned prime (minus 1)
+ will be coprime to *e* and thus suitable for RSA where
+ *e* is the public exponent.
+ false_positive_prob (float):
+ The statistical probability for the result not to be actually a
+ prime. It defaults to 10\ :sup:`-6`.
+ Note that the real probability of a false-positive is far less. This is
+ just the mathematically provable limit.
+ randfunc (callable):
+ A function that takes a parameter *N* and that returns
+ a random byte string of such length.
+ If omitted, :func:`Cryptodome.Random.get_random_bytes` is used.
+ Return:
+ The new strong prime.
+
+ .. deprecated:: 3.0
+ This function is for internal use only and may be renamed or removed in
+ the future.
+ """
+
+ # This function was implemented following the
+ # instructions found in the paper:
+ # "FAST GENERATION OF RANDOM, STRONG RSA PRIMES"
+ # by Robert D. Silverman
+ # RSA Laboratories
+ # May 17, 1997
+ # which by the time of writing could be freely downloaded here:
+ # http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.17.2713&rep=rep1&type=pdf
+
+ if randfunc is None:
+ randfunc = Random.get_random_bytes
+
+ # Use the accelerator if available
+ if _fastmath is not None:
+ return _fastmath.getStrongPrime(long(N), long(e), false_positive_prob,
+ randfunc)
+
+ if (N < 512) or ((N % 128) != 0):
+ raise ValueError ("bits must be multiple of 128 and > 512")
+
+ rabin_miller_rounds = int(math.ceil(-math.log(false_positive_prob)/math.log(4)))
+
+ # calculate range for X
+ # lower_bound = sqrt(2) * 2^{511 + 128*x}
+ # upper_bound = 2^{512 + 128*x} - 1
+ x = (N - 512) >> 7;
+ # We need to approximate the sqrt(2) in the lower_bound by an integer
+ # expression because floating point math overflows with these numbers
+ lower_bound = (14142135623730950489 * (2 ** (511 + 128*x))) // 10000000000000000000
+ upper_bound = (1 << (512 + 128*x)) - 1
+ # Randomly choose X in calculated range
+ X = getRandomRange (lower_bound, upper_bound, randfunc)
+
+ # generate p1 and p2
+ p = [0, 0]
+ for i in (0, 1):
+ # randomly choose 101-bit y
+ y = getRandomNBitInteger (101, randfunc)
+ # initialize the field for sieving
+ field = [0] * 5 * len (sieve_base)
+ # sieve the field
+ for prime in sieve_base:
+ offset = y % prime
+ for j in iter_range((prime - offset) % prime, len (field), prime):
+ field[j] = 1
+
+ # look for suitable p[i] starting at y
+ result = 0
+ for j in range(len(field)):
+ composite = field[j]
+ # look for next canidate
+ if composite:
+ continue
+ tmp = y + j
+ result = _rabinMillerTest (tmp, rabin_miller_rounds)
+ if result > 0:
+ p[i] = tmp
+ break
+ if result == 0:
+ raise RuntimeError ("Couln't find prime in field. "
+ "Developer: Increase field_size")
+
+ # Calculate R
+ # R = (p2^{-1} mod p1) * p2 - (p1^{-1} mod p2) * p1
+ tmp1 = inverse (p[1], p[0]) * p[1] # (p2^-1 mod p1)*p2
+ tmp2 = inverse (p[0], p[1]) * p[0] # (p1^-1 mod p2)*p1
+ R = tmp1 - tmp2 # (p2^-1 mod p1)*p2 - (p1^-1 mod p2)*p1
+
+ # search for final prime number starting by Y0
+ # Y0 = X + (R - X mod p1p2)
+ increment = p[0] * p[1]
+ X = X + (R - (X % increment))
+ while 1:
+ is_possible_prime = 1
+ # first check candidate against sieve_base
+ for prime in sieve_base:
+ if (X % prime) == 0:
+ is_possible_prime = 0
+ break
+ # if e is given make sure that e and X-1 are coprime
+ # this is not necessarily a strong prime criterion but useful when
+ # creating them for RSA where the p-1 and q-1 should be coprime to
+ # the public exponent e
+ if e and is_possible_prime:
+ if e & 1:
+ if GCD(e, X-1) != 1:
+ is_possible_prime = 0
+ else:
+ if GCD(e, (X-1) // 2) != 1:
+ is_possible_prime = 0
+
+ # do some Rabin-Miller-Tests
+ if is_possible_prime:
+ result = _rabinMillerTest (X, rabin_miller_rounds)
+ if result > 0:
+ break
+ X += increment
+ # abort when X has more bits than requested
+ # TODO: maybe we shouldn't abort but rather start over.
+ if X >= 1 << N:
+ raise RuntimeError ("Couln't find prime in field. "
+ "Developer: Increase field_size")
+ return X
+
+def isPrime(N, false_positive_prob=1e-6, randfunc=None):
+ r"""Test if a number *N* is a prime.
+
+ Args:
+ false_positive_prob (float):
+ The statistical probability for the result not to be actually a
+ prime. It defaults to 10\ :sup:`-6`.
+ Note that the real probability of a false-positive is far less.
+ This is just the mathematically provable limit.
+ randfunc (callable):
+ A function that takes a parameter *N* and that returns
+ a random byte string of such length.
+ If omitted, :func:`Cryptodome.Random.get_random_bytes` is used.
+
+ Return:
+ `True` is the input is indeed prime.
+ """
+
+ if randfunc is None:
+ randfunc = Random.get_random_bytes
+
+ if _fastmath is not None:
+ return _fastmath.isPrime(long(N), false_positive_prob, randfunc)
+
+ if N < 3 or N & 1 == 0:
+ return N == 2
+ for p in sieve_base:
+ if N == p:
+ return 1
+ if N % p == 0:
+ return 0
+
+ rounds = int(math.ceil(-math.log(false_positive_prob)/math.log(4)))
+ return _rabinMillerTest(N, rounds, randfunc)
+
+
+# Improved conversion functions contributed by Barry Warsaw, after
+# careful benchmarking
+
+import struct
+
+def long_to_bytes(n, blocksize=0):
+ """Convert an integer to a byte string.
+
+ In Python 3.2+, use the native method instead::
+
+ >>> n.to_bytes(blocksize, 'big')
+
+ For instance::
+
+ >>> n = 80
+ >>> n.to_bytes(2, 'big')
+ b'\x00P'
+
+ If the optional :data:`blocksize` is provided and greater than zero,
+ the byte string is padded with binary zeros (on the front) so that
+ the total length of the output is a multiple of blocksize.
+
+ If :data:`blocksize` is zero or not provided, the byte string will
+ be of minimal length.
+ """
+ # after much testing, this algorithm was deemed to be the fastest
+ s = b''
+ n = int(n)
+ pack = struct.pack
+ while n > 0:
+ s = pack('>I', n & 0xffffffff) + s
+ n = n >> 32
+ # strip off leading zeros
+ for i in range(len(s)):
+ if s[i] != b'\x00'[0]:
+ break
+ else:
+ # only happens when n == 0
+ s = b'\x00'
+ i = 0
+ s = s[i:]
+ # add back some pad bytes. this could be done more efficiently w.r.t. the
+ # de-padding being done above, but sigh...
+ if blocksize > 0 and len(s) % blocksize:
+ s = (blocksize - len(s) % blocksize) * b'\x00' + s
+ return s
+
+def bytes_to_long(s):
+ """Convert a byte string to a long integer (big endian).
+
+ In Python 3.2+, use the native method instead::
+
+ >>> int.from_bytes(s, 'big')
+
+ For instance::
+
+ >>> int.from_bytes(b'\x00P', 'big')
+ 80
+
+ This is (essentially) the inverse of :func:`long_to_bytes`.
+ """
+ acc = 0
+
+ unpack = struct.unpack
+
+ # Up to Python 2.7.4, struct.unpack can't work with bytearrays nor
+ # memoryviews
+ if sys.version_info[0:3] < (2, 7, 4):
+ if isinstance(s, bytearray):
+ s = bytes(s)
+ elif isinstance(s, _memoryview):
+ s = s.tobytes()
+
+ length = len(s)
+ if length % 4:
+ extra = (4 - length % 4)
+ s = b'\x00' * extra + s
+ length = length + extra
+ for i in range(0, length, 4):
+ acc = (acc << 32) + unpack('>I', s[i:i+4])[0]
+ return acc
+
+
+# For backwards compatibility...
+import warnings
+def long2str(n, blocksize=0):
+ warnings.warn("long2str() has been replaced by long_to_bytes()")
+ return long_to_bytes(n, blocksize)
+def str2long(s):
+ warnings.warn("str2long() has been replaced by bytes_to_long()")
+ return bytes_to_long(s)
+
+
+# The first 10000 primes used for checking primality.
+# This should be enough to eliminate most of the odd
+# numbers before needing to do a Rabin-Miller test at all.
+sieve_base = (
+ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
+ 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
+ 73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
+ 127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
+ 179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
+ 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
+ 283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
+ 353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
+ 419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
+ 467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
+ 547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
+ 607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
+ 661, 673, 677, 683, 691, 701, 709, 719, 727, 733,
+ 739, 743, 751, 757, 761, 769, 773, 787, 797, 809,
+ 811, 821, 823, 827, 829, 839, 853, 857, 859, 863,
+ 877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
+ 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013,
+ 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069,
+ 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151,
+ 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223,
+ 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
+ 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373,
+ 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451,
+ 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511,
+ 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583,
+ 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657,
+ 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733,
+ 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811,
+ 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889,
+ 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987,
+ 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053,
+ 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129,
+ 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213,
+ 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287,
+ 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357,
+ 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423,
+ 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531,
+ 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617,
+ 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687,
+ 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741,
+ 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819,
+ 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903,
+ 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999,
+ 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079,
+ 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181,
+ 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257,
+ 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331,
+ 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413,
+ 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511,
+ 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571,
+ 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643,
+ 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727,
+ 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821,
+ 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907,
+ 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989,
+ 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057,
+ 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139,
+ 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231,
+ 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297,
+ 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409,
+ 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493,
+ 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583,
+ 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657,
+ 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751,
+ 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831,
+ 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937,
+ 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003,
+ 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087,
+ 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179,
+ 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279,
+ 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387,
+ 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443,
+ 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521,
+ 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639,
+ 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693,
+ 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791,
+ 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857,
+ 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939,
+ 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053,
+ 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133,
+ 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221,
+ 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301,
+ 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367,
+ 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473,
+ 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571,
+ 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673,
+ 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761,
+ 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833,
+ 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917,
+ 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997,
+ 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103,
+ 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207,
+ 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297,
+ 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411,
+ 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499,
+ 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561,
+ 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643,
+ 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723,
+ 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829,
+ 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919,
+ 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017,
+ 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111,
+ 8117, 8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209, 8219,
+ 8221, 8231, 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291,
+ 8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, 8377, 8387,
+ 8389, 8419, 8423, 8429, 8431, 8443, 8447, 8461, 8467, 8501,
+ 8513, 8521, 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597,
+ 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677,
+ 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741,
+ 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831,
+ 8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929,
+ 8933, 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011,
+ 9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109,
+ 9127, 9133, 9137, 9151, 9157, 9161, 9173, 9181, 9187, 9199,
+ 9203, 9209, 9221, 9227, 9239, 9241, 9257, 9277, 9281, 9283,
+ 9293, 9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377,
+ 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439,
+ 9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521, 9533,
+ 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629, 9631,
+ 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733,
+ 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811,
+ 9817, 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887,
+ 9901, 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973, 10007,
+ 10009, 10037, 10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099,
+ 10103, 10111, 10133, 10139, 10141, 10151, 10159, 10163, 10169, 10177,
+ 10181, 10193, 10211, 10223, 10243, 10247, 10253, 10259, 10267, 10271,
+ 10273, 10289, 10301, 10303, 10313, 10321, 10331, 10333, 10337, 10343,
+ 10357, 10369, 10391, 10399, 10427, 10429, 10433, 10453, 10457, 10459,
+ 10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531, 10559, 10567,
+ 10589, 10597, 10601, 10607, 10613, 10627, 10631, 10639, 10651, 10657,
+ 10663, 10667, 10687, 10691, 10709, 10711, 10723, 10729, 10733, 10739,
+ 10753, 10771, 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859,
+ 10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937, 10939, 10949,
+ 10957, 10973, 10979, 10987, 10993, 11003, 11027, 11047, 11057, 11059,
+ 11069, 11071, 11083, 11087, 11093, 11113, 11117, 11119, 11131, 11149,
+ 11159, 11161, 11171, 11173, 11177, 11197, 11213, 11239, 11243, 11251,
+ 11257, 11261, 11273, 11279, 11287, 11299, 11311, 11317, 11321, 11329,
+ 11351, 11353, 11369, 11383, 11393, 11399, 11411, 11423, 11437, 11443,
+ 11447, 11467, 11471, 11483, 11489, 11491, 11497, 11503, 11519, 11527,
+ 11549, 11551, 11579, 11587, 11593, 11597, 11617, 11621, 11633, 11657,
+ 11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731, 11743, 11777,
+ 11779, 11783, 11789, 11801, 11807, 11813, 11821, 11827, 11831, 11833,
+ 11839, 11863, 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933,
+ 11939, 11941, 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011,
+ 12037, 12041, 12043, 12049, 12071, 12073, 12097, 12101, 12107, 12109,
+ 12113, 12119, 12143, 12149, 12157, 12161, 12163, 12197, 12203, 12211,
+ 12227, 12239, 12241, 12251, 12253, 12263, 12269, 12277, 12281, 12289,
+ 12301, 12323, 12329, 12343, 12347, 12373, 12377, 12379, 12391, 12401,
+ 12409, 12413, 12421, 12433, 12437, 12451, 12457, 12473, 12479, 12487,
+ 12491, 12497, 12503, 12511, 12517, 12527, 12539, 12541, 12547, 12553,
+ 12569, 12577, 12583, 12589, 12601, 12611, 12613, 12619, 12637, 12641,
+ 12647, 12653, 12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739,
+ 12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823, 12829,
+ 12841, 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919, 12923,
+ 12941, 12953, 12959, 12967, 12973, 12979, 12983, 13001, 13003, 13007,
+ 13009, 13033, 13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109,
+ 13121, 13127, 13147, 13151, 13159, 13163, 13171, 13177, 13183, 13187,
+ 13217, 13219, 13229, 13241, 13249, 13259, 13267, 13291, 13297, 13309,
+ 13313, 13327, 13331, 13337, 13339, 13367, 13381, 13397, 13399, 13411,
+ 13417, 13421, 13441, 13451, 13457, 13463, 13469, 13477, 13487, 13499,
+ 13513, 13523, 13537, 13553, 13567, 13577, 13591, 13597, 13613, 13619,
+ 13627, 13633, 13649, 13669, 13679, 13681, 13687, 13691, 13693, 13697,
+ 13709, 13711, 13721, 13723, 13729, 13751, 13757, 13759, 13763, 13781,
+ 13789, 13799, 13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879,
+ 13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, 13963, 13967,
+ 13997, 13999, 14009, 14011, 14029, 14033, 14051, 14057, 14071, 14081,
+ 14083, 14087, 14107, 14143, 14149, 14153, 14159, 14173, 14177, 14197,
+ 14207, 14221, 14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323,
+ 14327, 14341, 14347, 14369, 14387, 14389, 14401, 14407, 14411, 14419,
+ 14423, 14431, 14437, 14447, 14449, 14461, 14479, 14489, 14503, 14519,
+ 14533, 14537, 14543, 14549, 14551, 14557, 14561, 14563, 14591, 14593,
+ 14621, 14627, 14629, 14633, 14639, 14653, 14657, 14669, 14683, 14699,
+ 14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753, 14759, 14767,
+ 14771, 14779, 14783, 14797, 14813, 14821, 14827, 14831, 14843, 14851,
+ 14867, 14869, 14879, 14887, 14891, 14897, 14923, 14929, 14939, 14947,
+ 14951, 14957, 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073,
+ 15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137, 15139, 15149,
+ 15161, 15173, 15187, 15193, 15199, 15217, 15227, 15233, 15241, 15259,
+ 15263, 15269, 15271, 15277, 15287, 15289, 15299, 15307, 15313, 15319,
+ 15329, 15331, 15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401,
+ 15413, 15427, 15439, 15443, 15451, 15461, 15467, 15473, 15493, 15497,
+ 15511, 15527, 15541, 15551, 15559, 15569, 15581, 15583, 15601, 15607,
+ 15619, 15629, 15641, 15643, 15647, 15649, 15661, 15667, 15671, 15679,
+ 15683, 15727, 15731, 15733, 15737, 15739, 15749, 15761, 15767, 15773,
+ 15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859, 15877, 15881,
+ 15887, 15889, 15901, 15907, 15913, 15919, 15923, 15937, 15959, 15971,
+ 15973, 15991, 16001, 16007, 16033, 16057, 16061, 16063, 16067, 16069,
+ 16073, 16087, 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183,
+ 16187, 16189, 16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267,
+ 16273, 16301, 16319, 16333, 16339, 16349, 16361, 16363, 16369, 16381,
+ 16411, 16417, 16421, 16427, 16433, 16447, 16451, 16453, 16477, 16481,
+ 16487, 16493, 16519, 16529, 16547, 16553, 16561, 16567, 16573, 16603,
+ 16607, 16619, 16631, 16633, 16649, 16651, 16657, 16661, 16673, 16691,
+ 16693, 16699, 16703, 16729, 16741, 16747, 16759, 16763, 16787, 16811,
+ 16823, 16829, 16831, 16843, 16871, 16879, 16883, 16889, 16901, 16903,
+ 16921, 16927, 16931, 16937, 16943, 16963, 16979, 16981, 16987, 16993,
+ 17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053, 17077, 17093,
+ 17099, 17107, 17117, 17123, 17137, 17159, 17167, 17183, 17189, 17191,
+ 17203, 17207, 17209, 17231, 17239, 17257, 17291, 17293, 17299, 17317,
+ 17321, 17327, 17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389,
+ 17393, 17401, 17417, 17419, 17431, 17443, 17449, 17467, 17471, 17477,
+ 17483, 17489, 17491, 17497, 17509, 17519, 17539, 17551, 17569, 17573,
+ 17579, 17581, 17597, 17599, 17609, 17623, 17627, 17657, 17659, 17669,
+ 17681, 17683, 17707, 17713, 17729, 17737, 17747, 17749, 17761, 17783,
+ 17789, 17791, 17807, 17827, 17837, 17839, 17851, 17863, 17881, 17891,
+ 17903, 17909, 17911, 17921, 17923, 17929, 17939, 17957, 17959, 17971,
+ 17977, 17981, 17987, 17989, 18013, 18041, 18043, 18047, 18049, 18059,
+ 18061, 18077, 18089, 18097, 18119, 18121, 18127, 18131, 18133, 18143,
+ 18149, 18169, 18181, 18191, 18199, 18211, 18217, 18223, 18229, 18233,
+ 18251, 18253, 18257, 18269, 18287, 18289, 18301, 18307, 18311, 18313,
+ 18329, 18341, 18353, 18367, 18371, 18379, 18397, 18401, 18413, 18427,
+ 18433, 18439, 18443, 18451, 18457, 18461, 18481, 18493, 18503, 18517,
+ 18521, 18523, 18539, 18541, 18553, 18583, 18587, 18593, 18617, 18637,
+ 18661, 18671, 18679, 18691, 18701, 18713, 18719, 18731, 18743, 18749,
+ 18757, 18773, 18787, 18793, 18797, 18803, 18839, 18859, 18869, 18899,
+ 18911, 18913, 18917, 18919, 18947, 18959, 18973, 18979, 19001, 19009,
+ 19013, 19031, 19037, 19051, 19069, 19073, 19079, 19081, 19087, 19121,
+ 19139, 19141, 19157, 19163, 19181, 19183, 19207, 19211, 19213, 19219,
+ 19231, 19237, 19249, 19259, 19267, 19273, 19289, 19301, 19309, 19319,
+ 19333, 19373, 19379, 19381, 19387, 19391, 19403, 19417, 19421, 19423,
+ 19427, 19429, 19433, 19441, 19447, 19457, 19463, 19469, 19471, 19477,
+ 19483, 19489, 19501, 19507, 19531, 19541, 19543, 19553, 19559, 19571,
+ 19577, 19583, 19597, 19603, 19609, 19661, 19681, 19687, 19697, 19699,
+ 19709, 19717, 19727, 19739, 19751, 19753, 19759, 19763, 19777, 19793,
+ 19801, 19813, 19819, 19841, 19843, 19853, 19861, 19867, 19889, 19891,
+ 19913, 19919, 19927, 19937, 19949, 19961, 19963, 19973, 19979, 19991,
+ 19993, 19997, 20011, 20021, 20023, 20029, 20047, 20051, 20063, 20071,
+ 20089, 20101, 20107, 20113, 20117, 20123, 20129, 20143, 20147, 20149,
+ 20161, 20173, 20177, 20183, 20201, 20219, 20231, 20233, 20249, 20261,
+ 20269, 20287, 20297, 20323, 20327, 20333, 20341, 20347, 20353, 20357,
+ 20359, 20369, 20389, 20393, 20399, 20407, 20411, 20431, 20441, 20443,
+ 20477, 20479, 20483, 20507, 20509, 20521, 20533, 20543, 20549, 20551,
+ 20563, 20593, 20599, 20611, 20627, 20639, 20641, 20663, 20681, 20693,
+ 20707, 20717, 20719, 20731, 20743, 20747, 20749, 20753, 20759, 20771,
+ 20773, 20789, 20807, 20809, 20849, 20857, 20873, 20879, 20887, 20897,
+ 20899, 20903, 20921, 20929, 20939, 20947, 20959, 20963, 20981, 20983,
+ 21001, 21011, 21013, 21017, 21019, 21023, 21031, 21059, 21061, 21067,
+ 21089, 21101, 21107, 21121, 21139, 21143, 21149, 21157, 21163, 21169,
+ 21179, 21187, 21191, 21193, 21211, 21221, 21227, 21247, 21269, 21277,
+ 21283, 21313, 21317, 21319, 21323, 21341, 21347, 21377, 21379, 21383,
+ 21391, 21397, 21401, 21407, 21419, 21433, 21467, 21481, 21487, 21491,
+ 21493, 21499, 21503, 21517, 21521, 21523, 21529, 21557, 21559, 21563,
+ 21569, 21577, 21587, 21589, 21599, 21601, 21611, 21613, 21617, 21647,
+ 21649, 21661, 21673, 21683, 21701, 21713, 21727, 21737, 21739, 21751,
+ 21757, 21767, 21773, 21787, 21799, 21803, 21817, 21821, 21839, 21841,
+ 21851, 21859, 21863, 21871, 21881, 21893, 21911, 21929, 21937, 21943,
+ 21961, 21977, 21991, 21997, 22003, 22013, 22027, 22031, 22037, 22039,
+ 22051, 22063, 22067, 22073, 22079, 22091, 22093, 22109, 22111, 22123,
+ 22129, 22133, 22147, 22153, 22157, 22159, 22171, 22189, 22193, 22229,
+ 22247, 22259, 22271, 22273, 22277, 22279, 22283, 22291, 22303, 22307,
+ 22343, 22349, 22367, 22369, 22381, 22391, 22397, 22409, 22433, 22441,
+ 22447, 22453, 22469, 22481, 22483, 22501, 22511, 22531, 22541, 22543,
+ 22549, 22567, 22571, 22573, 22613, 22619, 22621, 22637, 22639, 22643,
+ 22651, 22669, 22679, 22691, 22697, 22699, 22709, 22717, 22721, 22727,
+ 22739, 22741, 22751, 22769, 22777, 22783, 22787, 22807, 22811, 22817,
+ 22853, 22859, 22861, 22871, 22877, 22901, 22907, 22921, 22937, 22943,
+ 22961, 22963, 22973, 22993, 23003, 23011, 23017, 23021, 23027, 23029,
+ 23039, 23041, 23053, 23057, 23059, 23063, 23071, 23081, 23087, 23099,
+ 23117, 23131, 23143, 23159, 23167, 23173, 23189, 23197, 23201, 23203,
+ 23209, 23227, 23251, 23269, 23279, 23291, 23293, 23297, 23311, 23321,
+ 23327, 23333, 23339, 23357, 23369, 23371, 23399, 23417, 23431, 23447,
+ 23459, 23473, 23497, 23509, 23531, 23537, 23539, 23549, 23557, 23561,
+ 23563, 23567, 23581, 23593, 23599, 23603, 23609, 23623, 23627, 23629,
+ 23633, 23663, 23669, 23671, 23677, 23687, 23689, 23719, 23741, 23743,
+ 23747, 23753, 23761, 23767, 23773, 23789, 23801, 23813, 23819, 23827,
+ 23831, 23833, 23857, 23869, 23873, 23879, 23887, 23893, 23899, 23909,
+ 23911, 23917, 23929, 23957, 23971, 23977, 23981, 23993, 24001, 24007,
+ 24019, 24023, 24029, 24043, 24049, 24061, 24071, 24077, 24083, 24091,
+ 24097, 24103, 24107, 24109, 24113, 24121, 24133, 24137, 24151, 24169,
+ 24179, 24181, 24197, 24203, 24223, 24229, 24239, 24247, 24251, 24281,
+ 24317, 24329, 24337, 24359, 24371, 24373, 24379, 24391, 24407, 24413,
+ 24419, 24421, 24439, 24443, 24469, 24473, 24481, 24499, 24509, 24517,
+ 24527, 24533, 24547, 24551, 24571, 24593, 24611, 24623, 24631, 24659,
+ 24671, 24677, 24683, 24691, 24697, 24709, 24733, 24749, 24763, 24767,
+ 24781, 24793, 24799, 24809, 24821, 24841, 24847, 24851, 24859, 24877,
+ 24889, 24907, 24917, 24919, 24923, 24943, 24953, 24967, 24971, 24977,
+ 24979, 24989, 25013, 25031, 25033, 25037, 25057, 25073, 25087, 25097,
+ 25111, 25117, 25121, 25127, 25147, 25153, 25163, 25169, 25171, 25183,
+ 25189, 25219, 25229, 25237, 25243, 25247, 25253, 25261, 25301, 25303,
+ 25307, 25309, 25321, 25339, 25343, 25349, 25357, 25367, 25373, 25391,
+ 25409, 25411, 25423, 25439, 25447, 25453, 25457, 25463, 25469, 25471,
+ 25523, 25537, 25541, 25561, 25577, 25579, 25583, 25589, 25601, 25603,
+ 25609, 25621, 25633, 25639, 25643, 25657, 25667, 25673, 25679, 25693,
+ 25703, 25717, 25733, 25741, 25747, 25759, 25763, 25771, 25793, 25799,
+ 25801, 25819, 25841, 25847, 25849, 25867, 25873, 25889, 25903, 25913,
+ 25919, 25931, 25933, 25939, 25943, 25951, 25969, 25981, 25997, 25999,
+ 26003, 26017, 26021, 26029, 26041, 26053, 26083, 26099, 26107, 26111,
+ 26113, 26119, 26141, 26153, 26161, 26171, 26177, 26183, 26189, 26203,
+ 26209, 26227, 26237, 26249, 26251, 26261, 26263, 26267, 26293, 26297,
+ 26309, 26317, 26321, 26339, 26347, 26357, 26371, 26387, 26393, 26399,
+ 26407, 26417, 26423, 26431, 26437, 26449, 26459, 26479, 26489, 26497,
+ 26501, 26513, 26539, 26557, 26561, 26573, 26591, 26597, 26627, 26633,
+ 26641, 26647, 26669, 26681, 26683, 26687, 26693, 26699, 26701, 26711,
+ 26713, 26717, 26723, 26729, 26731, 26737, 26759, 26777, 26783, 26801,
+ 26813, 26821, 26833, 26839, 26849, 26861, 26863, 26879, 26881, 26891,
+ 26893, 26903, 26921, 26927, 26947, 26951, 26953, 26959, 26981, 26987,
+ 26993, 27011, 27017, 27031, 27043, 27059, 27061, 27067, 27073, 27077,
+ 27091, 27103, 27107, 27109, 27127, 27143, 27179, 27191, 27197, 27211,
+ 27239, 27241, 27253, 27259, 27271, 27277, 27281, 27283, 27299, 27329,
+ 27337, 27361, 27367, 27397, 27407, 27409, 27427, 27431, 27437, 27449,
+ 27457, 27479, 27481, 27487, 27509, 27527, 27529, 27539, 27541, 27551,
+ 27581, 27583, 27611, 27617, 27631, 27647, 27653, 27673, 27689, 27691,
+ 27697, 27701, 27733, 27737, 27739, 27743, 27749, 27751, 27763, 27767,
+ 27773, 27779, 27791, 27793, 27799, 27803, 27809, 27817, 27823, 27827,
+ 27847, 27851, 27883, 27893, 27901, 27917, 27919, 27941, 27943, 27947,
+ 27953, 27961, 27967, 27983, 27997, 28001, 28019, 28027, 28031, 28051,
+ 28057, 28069, 28081, 28087, 28097, 28099, 28109, 28111, 28123, 28151,
+ 28163, 28181, 28183, 28201, 28211, 28219, 28229, 28277, 28279, 28283,
+ 28289, 28297, 28307, 28309, 28319, 28349, 28351, 28387, 28393, 28403,
+ 28409, 28411, 28429, 28433, 28439, 28447, 28463, 28477, 28493, 28499,
+ 28513, 28517, 28537, 28541, 28547, 28549, 28559, 28571, 28573, 28579,
+ 28591, 28597, 28603, 28607, 28619, 28621, 28627, 28631, 28643, 28649,
+ 28657, 28661, 28663, 28669, 28687, 28697, 28703, 28711, 28723, 28729,
+ 28751, 28753, 28759, 28771, 28789, 28793, 28807, 28813, 28817, 28837,
+ 28843, 28859, 28867, 28871, 28879, 28901, 28909, 28921, 28927, 28933,
+ 28949, 28961, 28979, 29009, 29017, 29021, 29023, 29027, 29033, 29059,
+ 29063, 29077, 29101, 29123, 29129, 29131, 29137, 29147, 29153, 29167,
+ 29173, 29179, 29191, 29201, 29207, 29209, 29221, 29231, 29243, 29251,
+ 29269, 29287, 29297, 29303, 29311, 29327, 29333, 29339, 29347, 29363,
+ 29383, 29387, 29389, 29399, 29401, 29411, 29423, 29429, 29437, 29443,
+ 29453, 29473, 29483, 29501, 29527, 29531, 29537, 29567, 29569, 29573,
+ 29581, 29587, 29599, 29611, 29629, 29633, 29641, 29663, 29669, 29671,
+ 29683, 29717, 29723, 29741, 29753, 29759, 29761, 29789, 29803, 29819,
+ 29833, 29837, 29851, 29863, 29867, 29873, 29879, 29881, 29917, 29921,
+ 29927, 29947, 29959, 29983, 29989, 30011, 30013, 30029, 30047, 30059,
+ 30071, 30089, 30091, 30097, 30103, 30109, 30113, 30119, 30133, 30137,
+ 30139, 30161, 30169, 30181, 30187, 30197, 30203, 30211, 30223, 30241,
+ 30253, 30259, 30269, 30271, 30293, 30307, 30313, 30319, 30323, 30341,
+ 30347, 30367, 30389, 30391, 30403, 30427, 30431, 30449, 30467, 30469,
+ 30491, 30493, 30497, 30509, 30517, 30529, 30539, 30553, 30557, 30559,
+ 30577, 30593, 30631, 30637, 30643, 30649, 30661, 30671, 30677, 30689,
+ 30697, 30703, 30707, 30713, 30727, 30757, 30763, 30773, 30781, 30803,
+ 30809, 30817, 30829, 30839, 30841, 30851, 30853, 30859, 30869, 30871,
+ 30881, 30893, 30911, 30931, 30937, 30941, 30949, 30971, 30977, 30983,
+ 31013, 31019, 31033, 31039, 31051, 31063, 31069, 31079, 31081, 31091,
+ 31121, 31123, 31139, 31147, 31151, 31153, 31159, 31177, 31181, 31183,
+ 31189, 31193, 31219, 31223, 31231, 31237, 31247, 31249, 31253, 31259,
+ 31267, 31271, 31277, 31307, 31319, 31321, 31327, 31333, 31337, 31357,
+ 31379, 31387, 31391, 31393, 31397, 31469, 31477, 31481, 31489, 31511,
+ 31513, 31517, 31531, 31541, 31543, 31547, 31567, 31573, 31583, 31601,
+ 31607, 31627, 31643, 31649, 31657, 31663, 31667, 31687, 31699, 31721,
+ 31723, 31727, 31729, 31741, 31751, 31769, 31771, 31793, 31799, 31817,
+ 31847, 31849, 31859, 31873, 31883, 31891, 31907, 31957, 31963, 31973,
+ 31981, 31991, 32003, 32009, 32027, 32029, 32051, 32057, 32059, 32063,
+ 32069, 32077, 32083, 32089, 32099, 32117, 32119, 32141, 32143, 32159,
+ 32173, 32183, 32189, 32191, 32203, 32213, 32233, 32237, 32251, 32257,
+ 32261, 32297, 32299, 32303, 32309, 32321, 32323, 32327, 32341, 32353,
+ 32359, 32363, 32369, 32371, 32377, 32381, 32401, 32411, 32413, 32423,
+ 32429, 32441, 32443, 32467, 32479, 32491, 32497, 32503, 32507, 32531,
+ 32533, 32537, 32561, 32563, 32569, 32573, 32579, 32587, 32603, 32609,
+ 32611, 32621, 32633, 32647, 32653, 32687, 32693, 32707, 32713, 32717,
+ 32719, 32749, 32771, 32779, 32783, 32789, 32797, 32801, 32803, 32831,
+ 32833, 32839, 32843, 32869, 32887, 32909, 32911, 32917, 32933, 32939,
+ 32941, 32957, 32969, 32971, 32983, 32987, 32993, 32999, 33013, 33023,
+ 33029, 33037, 33049, 33053, 33071, 33073, 33083, 33091, 33107, 33113,
+ 33119, 33149, 33151, 33161, 33179, 33181, 33191, 33199, 33203, 33211,
+ 33223, 33247, 33287, 33289, 33301, 33311, 33317, 33329, 33331, 33343,
+ 33347, 33349, 33353, 33359, 33377, 33391, 33403, 33409, 33413, 33427,
+ 33457, 33461, 33469, 33479, 33487, 33493, 33503, 33521, 33529, 33533,
+ 33547, 33563, 33569, 33577, 33581, 33587, 33589, 33599, 33601, 33613,
+ 33617, 33619, 33623, 33629, 33637, 33641, 33647, 33679, 33703, 33713,
+ 33721, 33739, 33749, 33751, 33757, 33767, 33769, 33773, 33791, 33797,
+ 33809, 33811, 33827, 33829, 33851, 33857, 33863, 33871, 33889, 33893,
+ 33911, 33923, 33931, 33937, 33941, 33961, 33967, 33997, 34019, 34031,
+ 34033, 34039, 34057, 34061, 34123, 34127, 34129, 34141, 34147, 34157,
+ 34159, 34171, 34183, 34211, 34213, 34217, 34231, 34253, 34259, 34261,
+ 34267, 34273, 34283, 34297, 34301, 34303, 34313, 34319, 34327, 34337,
+ 34351, 34361, 34367, 34369, 34381, 34403, 34421, 34429, 34439, 34457,
+ 34469, 34471, 34483, 34487, 34499, 34501, 34511, 34513, 34519, 34537,
+ 34543, 34549, 34583, 34589, 34591, 34603, 34607, 34613, 34631, 34649,
+ 34651, 34667, 34673, 34679, 34687, 34693, 34703, 34721, 34729, 34739,
+ 34747, 34757, 34759, 34763, 34781, 34807, 34819, 34841, 34843, 34847,
+ 34849, 34871, 34877, 34883, 34897, 34913, 34919, 34939, 34949, 34961,
+ 34963, 34981, 35023, 35027, 35051, 35053, 35059, 35069, 35081, 35083,
+ 35089, 35099, 35107, 35111, 35117, 35129, 35141, 35149, 35153, 35159,
+ 35171, 35201, 35221, 35227, 35251, 35257, 35267, 35279, 35281, 35291,
+ 35311, 35317, 35323, 35327, 35339, 35353, 35363, 35381, 35393, 35401,
+ 35407, 35419, 35423, 35437, 35447, 35449, 35461, 35491, 35507, 35509,
+ 35521, 35527, 35531, 35533, 35537, 35543, 35569, 35573, 35591, 35593,
+ 35597, 35603, 35617, 35671, 35677, 35729, 35731, 35747, 35753, 35759,
+ 35771, 35797, 35801, 35803, 35809, 35831, 35837, 35839, 35851, 35863,
+ 35869, 35879, 35897, 35899, 35911, 35923, 35933, 35951, 35963, 35969,
+ 35977, 35983, 35993, 35999, 36007, 36011, 36013, 36017, 36037, 36061,
+ 36067, 36073, 36083, 36097, 36107, 36109, 36131, 36137, 36151, 36161,
+ 36187, 36191, 36209, 36217, 36229, 36241, 36251, 36263, 36269, 36277,
+ 36293, 36299, 36307, 36313, 36319, 36341, 36343, 36353, 36373, 36383,
+ 36389, 36433, 36451, 36457, 36467, 36469, 36473, 36479, 36493, 36497,
+ 36523, 36527, 36529, 36541, 36551, 36559, 36563, 36571, 36583, 36587,
+ 36599, 36607, 36629, 36637, 36643, 36653, 36671, 36677, 36683, 36691,
+ 36697, 36709, 36713, 36721, 36739, 36749, 36761, 36767, 36779, 36781,
+ 36787, 36791, 36793, 36809, 36821, 36833, 36847, 36857, 36871, 36877,
+ 36887, 36899, 36901, 36913, 36919, 36923, 36929, 36931, 36943, 36947,
+ 36973, 36979, 36997, 37003, 37013, 37019, 37021, 37039, 37049, 37057,
+ 37061, 37087, 37097, 37117, 37123, 37139, 37159, 37171, 37181, 37189,
+ 37199, 37201, 37217, 37223, 37243, 37253, 37273, 37277, 37307, 37309,
+ 37313, 37321, 37337, 37339, 37357, 37361, 37363, 37369, 37379, 37397,
+ 37409, 37423, 37441, 37447, 37463, 37483, 37489, 37493, 37501, 37507,
+ 37511, 37517, 37529, 37537, 37547, 37549, 37561, 37567, 37571, 37573,
+ 37579, 37589, 37591, 37607, 37619, 37633, 37643, 37649, 37657, 37663,
+ 37691, 37693, 37699, 37717, 37747, 37781, 37783, 37799, 37811, 37813,
+ 37831, 37847, 37853, 37861, 37871, 37879, 37889, 37897, 37907, 37951,
+ 37957, 37963, 37967, 37987, 37991, 37993, 37997, 38011, 38039, 38047,
+ 38053, 38069, 38083, 38113, 38119, 38149, 38153, 38167, 38177, 38183,
+ 38189, 38197, 38201, 38219, 38231, 38237, 38239, 38261, 38273, 38281,
+ 38287, 38299, 38303, 38317, 38321, 38327, 38329, 38333, 38351, 38371,
+ 38377, 38393, 38431, 38447, 38449, 38453, 38459, 38461, 38501, 38543,
+ 38557, 38561, 38567, 38569, 38593, 38603, 38609, 38611, 38629, 38639,
+ 38651, 38653, 38669, 38671, 38677, 38693, 38699, 38707, 38711, 38713,
+ 38723, 38729, 38737, 38747, 38749, 38767, 38783, 38791, 38803, 38821,
+ 38833, 38839, 38851, 38861, 38867, 38873, 38891, 38903, 38917, 38921,
+ 38923, 38933, 38953, 38959, 38971, 38977, 38993, 39019, 39023, 39041,
+ 39043, 39047, 39079, 39089, 39097, 39103, 39107, 39113, 39119, 39133,
+ 39139, 39157, 39161, 39163, 39181, 39191, 39199, 39209, 39217, 39227,
+ 39229, 39233, 39239, 39241, 39251, 39293, 39301, 39313, 39317, 39323,
+ 39341, 39343, 39359, 39367, 39371, 39373, 39383, 39397, 39409, 39419,
+ 39439, 39443, 39451, 39461, 39499, 39503, 39509, 39511, 39521, 39541,
+ 39551, 39563, 39569, 39581, 39607, 39619, 39623, 39631, 39659, 39667,
+ 39671, 39679, 39703, 39709, 39719, 39727, 39733, 39749, 39761, 39769,
+ 39779, 39791, 39799, 39821, 39827, 39829, 39839, 39841, 39847, 39857,
+ 39863, 39869, 39877, 39883, 39887, 39901, 39929, 39937, 39953, 39971,
+ 39979, 39983, 39989, 40009, 40013, 40031, 40037, 40039, 40063, 40087,
+ 40093, 40099, 40111, 40123, 40127, 40129, 40151, 40153, 40163, 40169,
+ 40177, 40189, 40193, 40213, 40231, 40237, 40241, 40253, 40277, 40283,
+ 40289, 40343, 40351, 40357, 40361, 40387, 40423, 40427, 40429, 40433,
+ 40459, 40471, 40483, 40487, 40493, 40499, 40507, 40519, 40529, 40531,
+ 40543, 40559, 40577, 40583, 40591, 40597, 40609, 40627, 40637, 40639,
+ 40693, 40697, 40699, 40709, 40739, 40751, 40759, 40763, 40771, 40787,
+ 40801, 40813, 40819, 40823, 40829, 40841, 40847, 40849, 40853, 40867,
+ 40879, 40883, 40897, 40903, 40927, 40933, 40939, 40949, 40961, 40973,
+ 40993, 41011, 41017, 41023, 41039, 41047, 41051, 41057, 41077, 41081,
+ 41113, 41117, 41131, 41141, 41143, 41149, 41161, 41177, 41179, 41183,
+ 41189, 41201, 41203, 41213, 41221, 41227, 41231, 41233, 41243, 41257,
+ 41263, 41269, 41281, 41299, 41333, 41341, 41351, 41357, 41381, 41387,
+ 41389, 41399, 41411, 41413, 41443, 41453, 41467, 41479, 41491, 41507,
+ 41513, 41519, 41521, 41539, 41543, 41549, 41579, 41593, 41597, 41603,
+ 41609, 41611, 41617, 41621, 41627, 41641, 41647, 41651, 41659, 41669,
+ 41681, 41687, 41719, 41729, 41737, 41759, 41761, 41771, 41777, 41801,
+ 41809, 41813, 41843, 41849, 41851, 41863, 41879, 41887, 41893, 41897,
+ 41903, 41911, 41927, 41941, 41947, 41953, 41957, 41959, 41969, 41981,
+ 41983, 41999, 42013, 42017, 42019, 42023, 42043, 42061, 42071, 42073,
+ 42083, 42089, 42101, 42131, 42139, 42157, 42169, 42179, 42181, 42187,
+ 42193, 42197, 42209, 42221, 42223, 42227, 42239, 42257, 42281, 42283,
+ 42293, 42299, 42307, 42323, 42331, 42337, 42349, 42359, 42373, 42379,
+ 42391, 42397, 42403, 42407, 42409, 42433, 42437, 42443, 42451, 42457,
+ 42461, 42463, 42467, 42473, 42487, 42491, 42499, 42509, 42533, 42557,
+ 42569, 42571, 42577, 42589, 42611, 42641, 42643, 42649, 42667, 42677,
+ 42683, 42689, 42697, 42701, 42703, 42709, 42719, 42727, 42737, 42743,
+ 42751, 42767, 42773, 42787, 42793, 42797, 42821, 42829, 42839, 42841,
+ 42853, 42859, 42863, 42899, 42901, 42923, 42929, 42937, 42943, 42953,
+ 42961, 42967, 42979, 42989, 43003, 43013, 43019, 43037, 43049, 43051,
+ 43063, 43067, 43093, 43103, 43117, 43133, 43151, 43159, 43177, 43189,
+ 43201, 43207, 43223, 43237, 43261, 43271, 43283, 43291, 43313, 43319,
+ 43321, 43331, 43391, 43397, 43399, 43403, 43411, 43427, 43441, 43451,
+ 43457, 43481, 43487, 43499, 43517, 43541, 43543, 43573, 43577, 43579,
+ 43591, 43597, 43607, 43609, 43613, 43627, 43633, 43649, 43651, 43661,
+ 43669, 43691, 43711, 43717, 43721, 43753, 43759, 43777, 43781, 43783,
+ 43787, 43789, 43793, 43801, 43853, 43867, 43889, 43891, 43913, 43933,
+ 43943, 43951, 43961, 43963, 43969, 43973, 43987, 43991, 43997, 44017,
+ 44021, 44027, 44029, 44041, 44053, 44059, 44071, 44087, 44089, 44101,
+ 44111, 44119, 44123, 44129, 44131, 44159, 44171, 44179, 44189, 44201,
+ 44203, 44207, 44221, 44249, 44257, 44263, 44267, 44269, 44273, 44279,
+ 44281, 44293, 44351, 44357, 44371, 44381, 44383, 44389, 44417, 44449,
+ 44453, 44483, 44491, 44497, 44501, 44507, 44519, 44531, 44533, 44537,
+ 44543, 44549, 44563, 44579, 44587, 44617, 44621, 44623, 44633, 44641,
+ 44647, 44651, 44657, 44683, 44687, 44699, 44701, 44711, 44729, 44741,
+ 44753, 44771, 44773, 44777, 44789, 44797, 44809, 44819, 44839, 44843,
+ 44851, 44867, 44879, 44887, 44893, 44909, 44917, 44927, 44939, 44953,
+ 44959, 44963, 44971, 44983, 44987, 45007, 45013, 45053, 45061, 45077,
+ 45083, 45119, 45121, 45127, 45131, 45137, 45139, 45161, 45179, 45181,
+ 45191, 45197, 45233, 45247, 45259, 45263, 45281, 45289, 45293, 45307,
+ 45317, 45319, 45329, 45337, 45341, 45343, 45361, 45377, 45389, 45403,
+ 45413, 45427, 45433, 45439, 45481, 45491, 45497, 45503, 45523, 45533,
+ 45541, 45553, 45557, 45569, 45587, 45589, 45599, 45613, 45631, 45641,
+ 45659, 45667, 45673, 45677, 45691, 45697, 45707, 45737, 45751, 45757,
+ 45763, 45767, 45779, 45817, 45821, 45823, 45827, 45833, 45841, 45853,
+ 45863, 45869, 45887, 45893, 45943, 45949, 45953, 45959, 45971, 45979,
+ 45989, 46021, 46027, 46049, 46051, 46061, 46073, 46091, 46093, 46099,
+ 46103, 46133, 46141, 46147, 46153, 46171, 46181, 46183, 46187, 46199,
+ 46219, 46229, 46237, 46261, 46271, 46273, 46279, 46301, 46307, 46309,
+ 46327, 46337, 46349, 46351, 46381, 46399, 46411, 46439, 46441, 46447,
+ 46451, 46457, 46471, 46477, 46489, 46499, 46507, 46511, 46523, 46549,
+ 46559, 46567, 46573, 46589, 46591, 46601, 46619, 46633, 46639, 46643,
+ 46649, 46663, 46679, 46681, 46687, 46691, 46703, 46723, 46727, 46747,
+ 46751, 46757, 46769, 46771, 46807, 46811, 46817, 46819, 46829, 46831,
+ 46853, 46861, 46867, 46877, 46889, 46901, 46919, 46933, 46957, 46993,
+ 46997, 47017, 47041, 47051, 47057, 47059, 47087, 47093, 47111, 47119,
+ 47123, 47129, 47137, 47143, 47147, 47149, 47161, 47189, 47207, 47221,
+ 47237, 47251, 47269, 47279, 47287, 47293, 47297, 47303, 47309, 47317,
+ 47339, 47351, 47353, 47363, 47381, 47387, 47389, 47407, 47417, 47419,
+ 47431, 47441, 47459, 47491, 47497, 47501, 47507, 47513, 47521, 47527,
+ 47533, 47543, 47563, 47569, 47581, 47591, 47599, 47609, 47623, 47629,
+ 47639, 47653, 47657, 47659, 47681, 47699, 47701, 47711, 47713, 47717,
+ 47737, 47741, 47743, 47777, 47779, 47791, 47797, 47807, 47809, 47819,
+ 47837, 47843, 47857, 47869, 47881, 47903, 47911, 47917, 47933, 47939,
+ 47947, 47951, 47963, 47969, 47977, 47981, 48017, 48023, 48029, 48049,
+ 48073, 48079, 48091, 48109, 48119, 48121, 48131, 48157, 48163, 48179,
+ 48187, 48193, 48197, 48221, 48239, 48247, 48259, 48271, 48281, 48299,
+ 48311, 48313, 48337, 48341, 48353, 48371, 48383, 48397, 48407, 48409,
+ 48413, 48437, 48449, 48463, 48473, 48479, 48481, 48487, 48491, 48497,
+ 48523, 48527, 48533, 48539, 48541, 48563, 48571, 48589, 48593, 48611,
+ 48619, 48623, 48647, 48649, 48661, 48673, 48677, 48679, 48731, 48733,
+ 48751, 48757, 48761, 48767, 48779, 48781, 48787, 48799, 48809, 48817,
+ 48821, 48823, 48847, 48857, 48859, 48869, 48871, 48883, 48889, 48907,
+ 48947, 48953, 48973, 48989, 48991, 49003, 49009, 49019, 49031, 49033,
+ 49037, 49043, 49057, 49069, 49081, 49103, 49109, 49117, 49121, 49123,
+ 49139, 49157, 49169, 49171, 49177, 49193, 49199, 49201, 49207, 49211,
+ 49223, 49253, 49261, 49277, 49279, 49297, 49307, 49331, 49333, 49339,
+ 49363, 49367, 49369, 49391, 49393, 49409, 49411, 49417, 49429, 49433,
+ 49451, 49459, 49463, 49477, 49481, 49499, 49523, 49529, 49531, 49537,
+ 49547, 49549, 49559, 49597, 49603, 49613, 49627, 49633, 49639, 49663,
+ 49667, 49669, 49681, 49697, 49711, 49727, 49739, 49741, 49747, 49757,
+ 49783, 49787, 49789, 49801, 49807, 49811, 49823, 49831, 49843, 49853,
+ 49871, 49877, 49891, 49919, 49921, 49927, 49937, 49939, 49943, 49957,
+ 49991, 49993, 49999, 50021, 50023, 50033, 50047, 50051, 50053, 50069,
+ 50077, 50087, 50093, 50101, 50111, 50119, 50123, 50129, 50131, 50147,
+ 50153, 50159, 50177, 50207, 50221, 50227, 50231, 50261, 50263, 50273,
+ 50287, 50291, 50311, 50321, 50329, 50333, 50341, 50359, 50363, 50377,
+ 50383, 50387, 50411, 50417, 50423, 50441, 50459, 50461, 50497, 50503,
+ 50513, 50527, 50539, 50543, 50549, 50551, 50581, 50587, 50591, 50593,
+ 50599, 50627, 50647, 50651, 50671, 50683, 50707, 50723, 50741, 50753,
+ 50767, 50773, 50777, 50789, 50821, 50833, 50839, 50849, 50857, 50867,
+ 50873, 50891, 50893, 50909, 50923, 50929, 50951, 50957, 50969, 50971,
+ 50989, 50993, 51001, 51031, 51043, 51047, 51059, 51061, 51071, 51109,
+ 51131, 51133, 51137, 51151, 51157, 51169, 51193, 51197, 51199, 51203,
+ 51217, 51229, 51239, 51241, 51257, 51263, 51283, 51287, 51307, 51329,
+ 51341, 51343, 51347, 51349, 51361, 51383, 51407, 51413, 51419, 51421,
+ 51427, 51431, 51437, 51439, 51449, 51461, 51473, 51479, 51481, 51487,
+ 51503, 51511, 51517, 51521, 51539, 51551, 51563, 51577, 51581, 51593,
+ 51599, 51607, 51613, 51631, 51637, 51647, 51659, 51673, 51679, 51683,
+ 51691, 51713, 51719, 51721, 51749, 51767, 51769, 51787, 51797, 51803,
+ 51817, 51827, 51829, 51839, 51853, 51859, 51869, 51871, 51893, 51899,
+ 51907, 51913, 51929, 51941, 51949, 51971, 51973, 51977, 51991, 52009,
+ 52021, 52027, 52051, 52057, 52067, 52069, 52081, 52103, 52121, 52127,
+ 52147, 52153, 52163, 52177, 52181, 52183, 52189, 52201, 52223, 52237,
+ 52249, 52253, 52259, 52267, 52289, 52291, 52301, 52313, 52321, 52361,
+ 52363, 52369, 52379, 52387, 52391, 52433, 52453, 52457, 52489, 52501,
+ 52511, 52517, 52529, 52541, 52543, 52553, 52561, 52567, 52571, 52579,
+ 52583, 52609, 52627, 52631, 52639, 52667, 52673, 52691, 52697, 52709,
+ 52711, 52721, 52727, 52733, 52747, 52757, 52769, 52783, 52807, 52813,
+ 52817, 52837, 52859, 52861, 52879, 52883, 52889, 52901, 52903, 52919,
+ 52937, 52951, 52957, 52963, 52967, 52973, 52981, 52999, 53003, 53017,
+ 53047, 53051, 53069, 53077, 53087, 53089, 53093, 53101, 53113, 53117,
+ 53129, 53147, 53149, 53161, 53171, 53173, 53189, 53197, 53201, 53231,
+ 53233, 53239, 53267, 53269, 53279, 53281, 53299, 53309, 53323, 53327,
+ 53353, 53359, 53377, 53381, 53401, 53407, 53411, 53419, 53437, 53441,
+ 53453, 53479, 53503, 53507, 53527, 53549, 53551, 53569, 53591, 53593,
+ 53597, 53609, 53611, 53617, 53623, 53629, 53633, 53639, 53653, 53657,
+ 53681, 53693, 53699, 53717, 53719, 53731, 53759, 53773, 53777, 53783,
+ 53791, 53813, 53819, 53831, 53849, 53857, 53861, 53881, 53887, 53891,
+ 53897, 53899, 53917, 53923, 53927, 53939, 53951, 53959, 53987, 53993,
+ 54001, 54011, 54013, 54037, 54049, 54059, 54083, 54091, 54101, 54121,
+ 54133, 54139, 54151, 54163, 54167, 54181, 54193, 54217, 54251, 54269,
+ 54277, 54287, 54293, 54311, 54319, 54323, 54331, 54347, 54361, 54367,
+ 54371, 54377, 54401, 54403, 54409, 54413, 54419, 54421, 54437, 54443,
+ 54449, 54469, 54493, 54497, 54499, 54503, 54517, 54521, 54539, 54541,
+ 54547, 54559, 54563, 54577, 54581, 54583, 54601, 54617, 54623, 54629,
+ 54631, 54647, 54667, 54673, 54679, 54709, 54713, 54721, 54727, 54751,
+ 54767, 54773, 54779, 54787, 54799, 54829, 54833, 54851, 54869, 54877,
+ 54881, 54907, 54917, 54919, 54941, 54949, 54959, 54973, 54979, 54983,
+ 55001, 55009, 55021, 55049, 55051, 55057, 55061, 55073, 55079, 55103,
+ 55109, 55117, 55127, 55147, 55163, 55171, 55201, 55207, 55213, 55217,
+ 55219, 55229, 55243, 55249, 55259, 55291, 55313, 55331, 55333, 55337,
+ 55339, 55343, 55351, 55373, 55381, 55399, 55411, 55439, 55441, 55457,
+ 55469, 55487, 55501, 55511, 55529, 55541, 55547, 55579, 55589, 55603,
+ 55609, 55619, 55621, 55631, 55633, 55639, 55661, 55663, 55667, 55673,
+ 55681, 55691, 55697, 55711, 55717, 55721, 55733, 55763, 55787, 55793,
+ 55799, 55807, 55813, 55817, 55819, 55823, 55829, 55837, 55843, 55849,
+ 55871, 55889, 55897, 55901, 55903, 55921, 55927, 55931, 55933, 55949,
+ 55967, 55987, 55997, 56003, 56009, 56039, 56041, 56053, 56081, 56087,
+ 56093, 56099, 56101, 56113, 56123, 56131, 56149, 56167, 56171, 56179,
+ 56197, 56207, 56209, 56237, 56239, 56249, 56263, 56267, 56269, 56299,
+ 56311, 56333, 56359, 56369, 56377, 56383, 56393, 56401, 56417, 56431,
+ 56437, 56443, 56453, 56467, 56473, 56477, 56479, 56489, 56501, 56503,
+ 56509, 56519, 56527, 56531, 56533, 56543, 56569, 56591, 56597, 56599,
+ 56611, 56629, 56633, 56659, 56663, 56671, 56681, 56687, 56701, 56711,
+ 56713, 56731, 56737, 56747, 56767, 56773, 56779, 56783, 56807, 56809,
+ 56813, 56821, 56827, 56843, 56857, 56873, 56891, 56893, 56897, 56909,
+ 56911, 56921, 56923, 56929, 56941, 56951, 56957, 56963, 56983, 56989,
+ 56993, 56999, 57037, 57041, 57047, 57059, 57073, 57077, 57089, 57097,
+ 57107, 57119, 57131, 57139, 57143, 57149, 57163, 57173, 57179, 57191,
+ 57193, 57203, 57221, 57223, 57241, 57251, 57259, 57269, 57271, 57283,
+ 57287, 57301, 57329, 57331, 57347, 57349, 57367, 57373, 57383, 57389,
+ 57397, 57413, 57427, 57457, 57467, 57487, 57493, 57503, 57527, 57529,
+ 57557, 57559, 57571, 57587, 57593, 57601, 57637, 57641, 57649, 57653,
+ 57667, 57679, 57689, 57697, 57709, 57713, 57719, 57727, 57731, 57737,
+ 57751, 57773, 57781, 57787, 57791, 57793, 57803, 57809, 57829, 57839,
+ 57847, 57853, 57859, 57881, 57899, 57901, 57917, 57923, 57943, 57947,
+ 57973, 57977, 57991, 58013, 58027, 58031, 58043, 58049, 58057, 58061,
+ 58067, 58073, 58099, 58109, 58111, 58129, 58147, 58151, 58153, 58169,
+ 58171, 58189, 58193, 58199, 58207, 58211, 58217, 58229, 58231, 58237,
+ 58243, 58271, 58309, 58313, 58321, 58337, 58363, 58367, 58369, 58379,
+ 58391, 58393, 58403, 58411, 58417, 58427, 58439, 58441, 58451, 58453,
+ 58477, 58481, 58511, 58537, 58543, 58549, 58567, 58573, 58579, 58601,
+ 58603, 58613, 58631, 58657, 58661, 58679, 58687, 58693, 58699, 58711,
+ 58727, 58733, 58741, 58757, 58763, 58771, 58787, 58789, 58831, 58889,
+ 58897, 58901, 58907, 58909, 58913, 58921, 58937, 58943, 58963, 58967,
+ 58979, 58991, 58997, 59009, 59011, 59021, 59023, 59029, 59051, 59053,
+ 59063, 59069, 59077, 59083, 59093, 59107, 59113, 59119, 59123, 59141,
+ 59149, 59159, 59167, 59183, 59197, 59207, 59209, 59219, 59221, 59233,
+ 59239, 59243, 59263, 59273, 59281, 59333, 59341, 59351, 59357, 59359,
+ 59369, 59377, 59387, 59393, 59399, 59407, 59417, 59419, 59441, 59443,
+ 59447, 59453, 59467, 59471, 59473, 59497, 59509, 59513, 59539, 59557,
+ 59561, 59567, 59581, 59611, 59617, 59621, 59627, 59629, 59651, 59659,
+ 59663, 59669, 59671, 59693, 59699, 59707, 59723, 59729, 59743, 59747,
+ 59753, 59771, 59779, 59791, 59797, 59809, 59833, 59863, 59879, 59887,
+ 59921, 59929, 59951, 59957, 59971, 59981, 59999, 60013, 60017, 60029,
+ 60037, 60041, 60077, 60083, 60089, 60091, 60101, 60103, 60107, 60127,
+ 60133, 60139, 60149, 60161, 60167, 60169, 60209, 60217, 60223, 60251,
+ 60257, 60259, 60271, 60289, 60293, 60317, 60331, 60337, 60343, 60353,
+ 60373, 60383, 60397, 60413, 60427, 60443, 60449, 60457, 60493, 60497,
+ 60509, 60521, 60527, 60539, 60589, 60601, 60607, 60611, 60617, 60623,
+ 60631, 60637, 60647, 60649, 60659, 60661, 60679, 60689, 60703, 60719,
+ 60727, 60733, 60737, 60757, 60761, 60763, 60773, 60779, 60793, 60811,
+ 60821, 60859, 60869, 60887, 60889, 60899, 60901, 60913, 60917, 60919,
+ 60923, 60937, 60943, 60953, 60961, 61001, 61007, 61027, 61031, 61043,
+ 61051, 61057, 61091, 61099, 61121, 61129, 61141, 61151, 61153, 61169,
+ 61211, 61223, 61231, 61253, 61261, 61283, 61291, 61297, 61331, 61333,
+ 61339, 61343, 61357, 61363, 61379, 61381, 61403, 61409, 61417, 61441,
+ 61463, 61469, 61471, 61483, 61487, 61493, 61507, 61511, 61519, 61543,
+ 61547, 61553, 61559, 61561, 61583, 61603, 61609, 61613, 61627, 61631,
+ 61637, 61643, 61651, 61657, 61667, 61673, 61681, 61687, 61703, 61717,
+ 61723, 61729, 61751, 61757, 61781, 61813, 61819, 61837, 61843, 61861,
+ 61871, 61879, 61909, 61927, 61933, 61949, 61961, 61967, 61979, 61981,
+ 61987, 61991, 62003, 62011, 62017, 62039, 62047, 62053, 62057, 62071,
+ 62081, 62099, 62119, 62129, 62131, 62137, 62141, 62143, 62171, 62189,
+ 62191, 62201, 62207, 62213, 62219, 62233, 62273, 62297, 62299, 62303,
+ 62311, 62323, 62327, 62347, 62351, 62383, 62401, 62417, 62423, 62459,
+ 62467, 62473, 62477, 62483, 62497, 62501, 62507, 62533, 62539, 62549,
+ 62563, 62581, 62591, 62597, 62603, 62617, 62627, 62633, 62639, 62653,
+ 62659, 62683, 62687, 62701, 62723, 62731, 62743, 62753, 62761, 62773,
+ 62791, 62801, 62819, 62827, 62851, 62861, 62869, 62873, 62897, 62903,
+ 62921, 62927, 62929, 62939, 62969, 62971, 62981, 62983, 62987, 62989,
+ 63029, 63031, 63059, 63067, 63073, 63079, 63097, 63103, 63113, 63127,
+ 63131, 63149, 63179, 63197, 63199, 63211, 63241, 63247, 63277, 63281,
+ 63299, 63311, 63313, 63317, 63331, 63337, 63347, 63353, 63361, 63367,
+ 63377, 63389, 63391, 63397, 63409, 63419, 63421, 63439, 63443, 63463,
+ 63467, 63473, 63487, 63493, 63499, 63521, 63527, 63533, 63541, 63559,
+ 63577, 63587, 63589, 63599, 63601, 63607, 63611, 63617, 63629, 63647,
+ 63649, 63659, 63667, 63671, 63689, 63691, 63697, 63703, 63709, 63719,
+ 63727, 63737, 63743, 63761, 63773, 63781, 63793, 63799, 63803, 63809,
+ 63823, 63839, 63841, 63853, 63857, 63863, 63901, 63907, 63913, 63929,
+ 63949, 63977, 63997, 64007, 64013, 64019, 64033, 64037, 64063, 64067,
+ 64081, 64091, 64109, 64123, 64151, 64153, 64157, 64171, 64187, 64189,
+ 64217, 64223, 64231, 64237, 64271, 64279, 64283, 64301, 64303, 64319,
+ 64327, 64333, 64373, 64381, 64399, 64403, 64433, 64439, 64451, 64453,
+ 64483, 64489, 64499, 64513, 64553, 64567, 64577, 64579, 64591, 64601,
+ 64609, 64613, 64621, 64627, 64633, 64661, 64663, 64667, 64679, 64693,
+ 64709, 64717, 64747, 64763, 64781, 64783, 64793, 64811, 64817, 64849,
+ 64853, 64871, 64877, 64879, 64891, 64901, 64919, 64921, 64927, 64937,
+ 64951, 64969, 64997, 65003, 65011, 65027, 65029, 65033, 65053, 65063,
+ 65071, 65089, 65099, 65101, 65111, 65119, 65123, 65129, 65141, 65147,
+ 65167, 65171, 65173, 65179, 65183, 65203, 65213, 65239, 65257, 65267,
+ 65269, 65287, 65293, 65309, 65323, 65327, 65353, 65357, 65371, 65381,
+ 65393, 65407, 65413, 65419, 65423, 65437, 65447, 65449, 65479, 65497,
+ 65519, 65521, 65537, 65539, 65543, 65551, 65557, 65563, 65579, 65581,
+ 65587, 65599, 65609, 65617, 65629, 65633, 65647, 65651, 65657, 65677,
+ 65687, 65699, 65701, 65707, 65713, 65717, 65719, 65729, 65731, 65761,
+ 65777, 65789, 65809, 65827, 65831, 65837, 65839, 65843, 65851, 65867,
+ 65881, 65899, 65921, 65927, 65929, 65951, 65957, 65963, 65981, 65983,
+ 65993, 66029, 66037, 66041, 66047, 66067, 66071, 66083, 66089, 66103,
+ 66107, 66109, 66137, 66161, 66169, 66173, 66179, 66191, 66221, 66239,
+ 66271, 66293, 66301, 66337, 66343, 66347, 66359, 66361, 66373, 66377,
+ 66383, 66403, 66413, 66431, 66449, 66457, 66463, 66467, 66491, 66499,
+ 66509, 66523, 66529, 66533, 66541, 66553, 66569, 66571, 66587, 66593,
+ 66601, 66617, 66629, 66643, 66653, 66683, 66697, 66701, 66713, 66721,
+ 66733, 66739, 66749, 66751, 66763, 66791, 66797, 66809, 66821, 66841,
+ 66851, 66853, 66863, 66877, 66883, 66889, 66919, 66923, 66931, 66943,
+ 66947, 66949, 66959, 66973, 66977, 67003, 67021, 67033, 67043, 67049,
+ 67057, 67061, 67073, 67079, 67103, 67121, 67129, 67139, 67141, 67153,
+ 67157, 67169, 67181, 67187, 67189, 67211, 67213, 67217, 67219, 67231,
+ 67247, 67261, 67271, 67273, 67289, 67307, 67339, 67343, 67349, 67369,
+ 67391, 67399, 67409, 67411, 67421, 67427, 67429, 67433, 67447, 67453,
+ 67477, 67481, 67489, 67493, 67499, 67511, 67523, 67531, 67537, 67547,
+ 67559, 67567, 67577, 67579, 67589, 67601, 67607, 67619, 67631, 67651,
+ 67679, 67699, 67709, 67723, 67733, 67741, 67751, 67757, 67759, 67763,
+ 67777, 67783, 67789, 67801, 67807, 67819, 67829, 67843, 67853, 67867,
+ 67883, 67891, 67901, 67927, 67931, 67933, 67939, 67943, 67957, 67961,
+ 67967, 67979, 67987, 67993, 68023, 68041, 68053, 68059, 68071, 68087,
+ 68099, 68111, 68113, 68141, 68147, 68161, 68171, 68207, 68209, 68213,
+ 68219, 68227, 68239, 68261, 68279, 68281, 68311, 68329, 68351, 68371,
+ 68389, 68399, 68437, 68443, 68447, 68449, 68473, 68477, 68483, 68489,
+ 68491, 68501, 68507, 68521, 68531, 68539, 68543, 68567, 68581, 68597,
+ 68611, 68633, 68639, 68659, 68669, 68683, 68687, 68699, 68711, 68713,
+ 68729, 68737, 68743, 68749, 68767, 68771, 68777, 68791, 68813, 68819,
+ 68821, 68863, 68879, 68881, 68891, 68897, 68899, 68903, 68909, 68917,
+ 68927, 68947, 68963, 68993, 69001, 69011, 69019, 69029, 69031, 69061,
+ 69067, 69073, 69109, 69119, 69127, 69143, 69149, 69151, 69163, 69191,
+ 69193, 69197, 69203, 69221, 69233, 69239, 69247, 69257, 69259, 69263,
+ 69313, 69317, 69337, 69341, 69371, 69379, 69383, 69389, 69401, 69403,
+ 69427, 69431, 69439, 69457, 69463, 69467, 69473, 69481, 69491, 69493,
+ 69497, 69499, 69539, 69557, 69593, 69623, 69653, 69661, 69677, 69691,
+ 69697, 69709, 69737, 69739, 69761, 69763, 69767, 69779, 69809, 69821,
+ 69827, 69829, 69833, 69847, 69857, 69859, 69877, 69899, 69911, 69929,
+ 69931, 69941, 69959, 69991, 69997, 70001, 70003, 70009, 70019, 70039,
+ 70051, 70061, 70067, 70079, 70099, 70111, 70117, 70121, 70123, 70139,
+ 70141, 70157, 70163, 70177, 70181, 70183, 70199, 70201, 70207, 70223,
+ 70229, 70237, 70241, 70249, 70271, 70289, 70297, 70309, 70313, 70321,
+ 70327, 70351, 70373, 70379, 70381, 70393, 70423, 70429, 70439, 70451,
+ 70457, 70459, 70481, 70487, 70489, 70501, 70507, 70529, 70537, 70549,
+ 70571, 70573, 70583, 70589, 70607, 70619, 70621, 70627, 70639, 70657,
+ 70663, 70667, 70687, 70709, 70717, 70729, 70753, 70769, 70783, 70793,
+ 70823, 70841, 70843, 70849, 70853, 70867, 70877, 70879, 70891, 70901,
+ 70913, 70919, 70921, 70937, 70949, 70951, 70957, 70969, 70979, 70981,
+ 70991, 70997, 70999, 71011, 71023, 71039, 71059, 71069, 71081, 71089,
+ 71119, 71129, 71143, 71147, 71153, 71161, 71167, 71171, 71191, 71209,
+ 71233, 71237, 71249, 71257, 71261, 71263, 71287, 71293, 71317, 71327,
+ 71329, 71333, 71339, 71341, 71347, 71353, 71359, 71363, 71387, 71389,
+ 71399, 71411, 71413, 71419, 71429, 71437, 71443, 71453, 71471, 71473,
+ 71479, 71483, 71503, 71527, 71537, 71549, 71551, 71563, 71569, 71593,
+ 71597, 71633, 71647, 71663, 71671, 71693, 71699, 71707, 71711, 71713,
+ 71719, 71741, 71761, 71777, 71789, 71807, 71809, 71821, 71837, 71843,
+ 71849, 71861, 71867, 71879, 71881, 71887, 71899, 71909, 71917, 71933,
+ 71941, 71947, 71963, 71971, 71983, 71987, 71993, 71999, 72019, 72031,
+ 72043, 72047, 72053, 72073, 72077, 72089, 72091, 72101, 72103, 72109,
+ 72139, 72161, 72167, 72169, 72173, 72211, 72221, 72223, 72227, 72229,
+ 72251, 72253, 72269, 72271, 72277, 72287, 72307, 72313, 72337, 72341,
+ 72353, 72367, 72379, 72383, 72421, 72431, 72461, 72467, 72469, 72481,
+ 72493, 72497, 72503, 72533, 72547, 72551, 72559, 72577, 72613, 72617,
+ 72623, 72643, 72647, 72649, 72661, 72671, 72673, 72679, 72689, 72701,
+ 72707, 72719, 72727, 72733, 72739, 72763, 72767, 72797, 72817, 72823,
+ 72859, 72869, 72871, 72883, 72889, 72893, 72901, 72907, 72911, 72923,
+ 72931, 72937, 72949, 72953, 72959, 72973, 72977, 72997, 73009, 73013,
+ 73019, 73037, 73039, 73043, 73061, 73063, 73079, 73091, 73121, 73127,
+ 73133, 73141, 73181, 73189, 73237, 73243, 73259, 73277, 73291, 73303,
+ 73309, 73327, 73331, 73351, 73361, 73363, 73369, 73379, 73387, 73417,
+ 73421, 73433, 73453, 73459, 73471, 73477, 73483, 73517, 73523, 73529,
+ 73547, 73553, 73561, 73571, 73583, 73589, 73597, 73607, 73609, 73613,
+ 73637, 73643, 73651, 73673, 73679, 73681, 73693, 73699, 73709, 73721,
+ 73727, 73751, 73757, 73771, 73783, 73819, 73823, 73847, 73849, 73859,
+ 73867, 73877, 73883, 73897, 73907, 73939, 73943, 73951, 73961, 73973,
+ 73999, 74017, 74021, 74027, 74047, 74051, 74071, 74077, 74093, 74099,
+ 74101, 74131, 74143, 74149, 74159, 74161, 74167, 74177, 74189, 74197,
+ 74201, 74203, 74209, 74219, 74231, 74257, 74279, 74287, 74293, 74297,
+ 74311, 74317, 74323, 74353, 74357, 74363, 74377, 74381, 74383, 74411,
+ 74413, 74419, 74441, 74449, 74453, 74471, 74489, 74507, 74509, 74521,
+ 74527, 74531, 74551, 74561, 74567, 74573, 74587, 74597, 74609, 74611,
+ 74623, 74653, 74687, 74699, 74707, 74713, 74717, 74719, 74729, 74731,
+ 74747, 74759, 74761, 74771, 74779, 74797, 74821, 74827, 74831, 74843,
+ 74857, 74861, 74869, 74873, 74887, 74891, 74897, 74903, 74923, 74929,
+ 74933, 74941, 74959, 75011, 75013, 75017, 75029, 75037, 75041, 75079,
+ 75083, 75109, 75133, 75149, 75161, 75167, 75169, 75181, 75193, 75209,
+ 75211, 75217, 75223, 75227, 75239, 75253, 75269, 75277, 75289, 75307,
+ 75323, 75329, 75337, 75347, 75353, 75367, 75377, 75389, 75391, 75401,
+ 75403, 75407, 75431, 75437, 75479, 75503, 75511, 75521, 75527, 75533,
+ 75539, 75541, 75553, 75557, 75571, 75577, 75583, 75611, 75617, 75619,
+ 75629, 75641, 75653, 75659, 75679, 75683, 75689, 75703, 75707, 75709,
+ 75721, 75731, 75743, 75767, 75773, 75781, 75787, 75793, 75797, 75821,
+ 75833, 75853, 75869, 75883, 75913, 75931, 75937, 75941, 75967, 75979,
+ 75983, 75989, 75991, 75997, 76001, 76003, 76031, 76039, 76079, 76081,
+ 76091, 76099, 76103, 76123, 76129, 76147, 76157, 76159, 76163, 76207,
+ 76213, 76231, 76243, 76249, 76253, 76259, 76261, 76283, 76289, 76303,
+ 76333, 76343, 76367, 76369, 76379, 76387, 76403, 76421, 76423, 76441,
+ 76463, 76471, 76481, 76487, 76493, 76507, 76511, 76519, 76537, 76541,
+ 76543, 76561, 76579, 76597, 76603, 76607, 76631, 76649, 76651, 76667,
+ 76673, 76679, 76697, 76717, 76733, 76753, 76757, 76771, 76777, 76781,
+ 76801, 76819, 76829, 76831, 76837, 76847, 76871, 76873, 76883, 76907,
+ 76913, 76919, 76943, 76949, 76961, 76963, 76991, 77003, 77017, 77023,
+ 77029, 77041, 77047, 77069, 77081, 77093, 77101, 77137, 77141, 77153,
+ 77167, 77171, 77191, 77201, 77213, 77237, 77239, 77243, 77249, 77261,
+ 77263, 77267, 77269, 77279, 77291, 77317, 77323, 77339, 77347, 77351,
+ 77359, 77369, 77377, 77383, 77417, 77419, 77431, 77447, 77471, 77477,
+ 77479, 77489, 77491, 77509, 77513, 77521, 77527, 77543, 77549, 77551,
+ 77557, 77563, 77569, 77573, 77587, 77591, 77611, 77617, 77621, 77641,
+ 77647, 77659, 77681, 77687, 77689, 77699, 77711, 77713, 77719, 77723,
+ 77731, 77743, 77747, 77761, 77773, 77783, 77797, 77801, 77813, 77839,
+ 77849, 77863, 77867, 77893, 77899, 77929, 77933, 77951, 77969, 77977,
+ 77983, 77999, 78007, 78017, 78031, 78041, 78049, 78059, 78079, 78101,
+ 78121, 78137, 78139, 78157, 78163, 78167, 78173, 78179, 78191, 78193,
+ 78203, 78229, 78233, 78241, 78259, 78277, 78283, 78301, 78307, 78311,
+ 78317, 78341, 78347, 78367, 78401, 78427, 78437, 78439, 78467, 78479,
+ 78487, 78497, 78509, 78511, 78517, 78539, 78541, 78553, 78569, 78571,
+ 78577, 78583, 78593, 78607, 78623, 78643, 78649, 78653, 78691, 78697,
+ 78707, 78713, 78721, 78737, 78779, 78781, 78787, 78791, 78797, 78803,
+ 78809, 78823, 78839, 78853, 78857, 78877, 78887, 78889, 78893, 78901,
+ 78919, 78929, 78941, 78977, 78979, 78989, 79031, 79039, 79043, 79063,
+ 79087, 79103, 79111, 79133, 79139, 79147, 79151, 79153, 79159, 79181,
+ 79187, 79193, 79201, 79229, 79231, 79241, 79259, 79273, 79279, 79283,
+ 79301, 79309, 79319, 79333, 79337, 79349, 79357, 79367, 79379, 79393,
+ 79397, 79399, 79411, 79423, 79427, 79433, 79451, 79481, 79493, 79531,
+ 79537, 79549, 79559, 79561, 79579, 79589, 79601, 79609, 79613, 79621,
+ 79627, 79631, 79633, 79657, 79669, 79687, 79691, 79693, 79697, 79699,
+ 79757, 79769, 79777, 79801, 79811, 79813, 79817, 79823, 79829, 79841,
+ 79843, 79847, 79861, 79867, 79873, 79889, 79901, 79903, 79907, 79939,
+ 79943, 79967, 79973, 79979, 79987, 79997, 79999, 80021, 80039, 80051,
+ 80071, 80077, 80107, 80111, 80141, 80147, 80149, 80153, 80167, 80173,
+ 80177, 80191, 80207, 80209, 80221, 80231, 80233, 80239, 80251, 80263,
+ 80273, 80279, 80287, 80309, 80317, 80329, 80341, 80347, 80363, 80369,
+ 80387, 80407, 80429, 80447, 80449, 80471, 80473, 80489, 80491, 80513,
+ 80527, 80537, 80557, 80567, 80599, 80603, 80611, 80621, 80627, 80629,
+ 80651, 80657, 80669, 80671, 80677, 80681, 80683, 80687, 80701, 80713,
+ 80737, 80747, 80749, 80761, 80777, 80779, 80783, 80789, 80803, 80809,
+ 80819, 80831, 80833, 80849, 80863, 80897, 80909, 80911, 80917, 80923,
+ 80929, 80933, 80953, 80963, 80989, 81001, 81013, 81017, 81019, 81023,
+ 81031, 81041, 81043, 81047, 81049, 81071, 81077, 81083, 81097, 81101,
+ 81119, 81131, 81157, 81163, 81173, 81181, 81197, 81199, 81203, 81223,
+ 81233, 81239, 81281, 81283, 81293, 81299, 81307, 81331, 81343, 81349,
+ 81353, 81359, 81371, 81373, 81401, 81409, 81421, 81439, 81457, 81463,
+ 81509, 81517, 81527, 81533, 81547, 81551, 81553, 81559, 81563, 81569,
+ 81611, 81619, 81629, 81637, 81647, 81649, 81667, 81671, 81677, 81689,
+ 81701, 81703, 81707, 81727, 81737, 81749, 81761, 81769, 81773, 81799,
+ 81817, 81839, 81847, 81853, 81869, 81883, 81899, 81901, 81919, 81929,
+ 81931, 81937, 81943, 81953, 81967, 81971, 81973, 82003, 82007, 82009,
+ 82013, 82021, 82031, 82037, 82039, 82051, 82067, 82073, 82129, 82139,
+ 82141, 82153, 82163, 82171, 82183, 82189, 82193, 82207, 82217, 82219,
+ 82223, 82231, 82237, 82241, 82261, 82267, 82279, 82301, 82307, 82339,
+ 82349, 82351, 82361, 82373, 82387, 82393, 82421, 82457, 82463, 82469,
+ 82471, 82483, 82487, 82493, 82499, 82507, 82529, 82531, 82549, 82559,
+ 82561, 82567, 82571, 82591, 82601, 82609, 82613, 82619, 82633, 82651,
+ 82657, 82699, 82721, 82723, 82727, 82729, 82757, 82759, 82763, 82781,
+ 82787, 82793, 82799, 82811, 82813, 82837, 82847, 82883, 82889, 82891,
+ 82903, 82913, 82939, 82963, 82981, 82997, 83003, 83009, 83023, 83047,
+ 83059, 83063, 83071, 83077, 83089, 83093, 83101, 83117, 83137, 83177,
+ 83203, 83207, 83219, 83221, 83227, 83231, 83233, 83243, 83257, 83267,
+ 83269, 83273, 83299, 83311, 83339, 83341, 83357, 83383, 83389, 83399,
+ 83401, 83407, 83417, 83423, 83431, 83437, 83443, 83449, 83459, 83471,
+ 83477, 83497, 83537, 83557, 83561, 83563, 83579, 83591, 83597, 83609,
+ 83617, 83621, 83639, 83641, 83653, 83663, 83689, 83701, 83717, 83719,
+ 83737, 83761, 83773, 83777, 83791, 83813, 83833, 83843, 83857, 83869,
+ 83873, 83891, 83903, 83911, 83921, 83933, 83939, 83969, 83983, 83987,
+ 84011, 84017, 84047, 84053, 84059, 84061, 84067, 84089, 84121, 84127,
+ 84131, 84137, 84143, 84163, 84179, 84181, 84191, 84199, 84211, 84221,
+ 84223, 84229, 84239, 84247, 84263, 84299, 84307, 84313, 84317, 84319,
+ 84347, 84349, 84377, 84389, 84391, 84401, 84407, 84421, 84431, 84437,
+ 84443, 84449, 84457, 84463, 84467, 84481, 84499, 84503, 84509, 84521,
+ 84523, 84533, 84551, 84559, 84589, 84629, 84631, 84649, 84653, 84659,
+ 84673, 84691, 84697, 84701, 84713, 84719, 84731, 84737, 84751, 84761,
+ 84787, 84793, 84809, 84811, 84827, 84857, 84859, 84869, 84871, 84913,
+ 84919, 84947, 84961, 84967, 84977, 84979, 84991, 85009, 85021, 85027,
+ 85037, 85049, 85061, 85081, 85087, 85091, 85093, 85103, 85109, 85121,
+ 85133, 85147, 85159, 85193, 85199, 85201, 85213, 85223, 85229, 85237,
+ 85243, 85247, 85259, 85297, 85303, 85313, 85331, 85333, 85361, 85363,
+ 85369, 85381, 85411, 85427, 85429, 85439, 85447, 85451, 85453, 85469,
+ 85487, 85513, 85517, 85523, 85531, 85549, 85571, 85577, 85597, 85601,
+ 85607, 85619, 85621, 85627, 85639, 85643, 85661, 85667, 85669, 85691,
+ 85703, 85711, 85717, 85733, 85751, 85781, 85793, 85817, 85819, 85829,
+ 85831, 85837, 85843, 85847, 85853, 85889, 85903, 85909, 85931, 85933,
+ 85991, 85999, 86011, 86017, 86027, 86029, 86069, 86077, 86083, 86111,
+ 86113, 86117, 86131, 86137, 86143, 86161, 86171, 86179, 86183, 86197,
+ 86201, 86209, 86239, 86243, 86249, 86257, 86263, 86269, 86287, 86291,
+ 86293, 86297, 86311, 86323, 86341, 86351, 86353, 86357, 86369, 86371,
+ 86381, 86389, 86399, 86413, 86423, 86441, 86453, 86461, 86467, 86477,
+ 86491, 86501, 86509, 86531, 86533, 86539, 86561, 86573, 86579, 86587,
+ 86599, 86627, 86629, 86677, 86689, 86693, 86711, 86719, 86729, 86743,
+ 86753, 86767, 86771, 86783, 86813, 86837, 86843, 86851, 86857, 86861,
+ 86869, 86923, 86927, 86929, 86939, 86951, 86959, 86969, 86981, 86993,
+ 87011, 87013, 87037, 87041, 87049, 87071, 87083, 87103, 87107, 87119,
+ 87121, 87133, 87149, 87151, 87179, 87181, 87187, 87211, 87221, 87223,
+ 87251, 87253, 87257, 87277, 87281, 87293, 87299, 87313, 87317, 87323,
+ 87337, 87359, 87383, 87403, 87407, 87421, 87427, 87433, 87443, 87473,
+ 87481, 87491, 87509, 87511, 87517, 87523, 87539, 87541, 87547, 87553,
+ 87557, 87559, 87583, 87587, 87589, 87613, 87623, 87629, 87631, 87641,
+ 87643, 87649, 87671, 87679, 87683, 87691, 87697, 87701, 87719, 87721,
+ 87739, 87743, 87751, 87767, 87793, 87797, 87803, 87811, 87833, 87853,
+ 87869, 87877, 87881, 87887, 87911, 87917, 87931, 87943, 87959, 87961,
+ 87973, 87977, 87991, 88001, 88003, 88007, 88019, 88037, 88069, 88079,
+ 88093, 88117, 88129, 88169, 88177, 88211, 88223, 88237, 88241, 88259,
+ 88261, 88289, 88301, 88321, 88327, 88337, 88339, 88379, 88397, 88411,
+ 88423, 88427, 88463, 88469, 88471, 88493, 88499, 88513, 88523, 88547,
+ 88589, 88591, 88607, 88609, 88643, 88651, 88657, 88661, 88663, 88667,
+ 88681, 88721, 88729, 88741, 88747, 88771, 88789, 88793, 88799, 88801,
+ 88807, 88811, 88813, 88817, 88819, 88843, 88853, 88861, 88867, 88873,
+ 88883, 88897, 88903, 88919, 88937, 88951, 88969, 88993, 88997, 89003,
+ 89009, 89017, 89021, 89041, 89051, 89057, 89069, 89071, 89083, 89087,
+ 89101, 89107, 89113, 89119, 89123, 89137, 89153, 89189, 89203, 89209,
+ 89213, 89227, 89231, 89237, 89261, 89269, 89273, 89293, 89303, 89317,
+ 89329, 89363, 89371, 89381, 89387, 89393, 89399, 89413, 89417, 89431,
+ 89443, 89449, 89459, 89477, 89491, 89501, 89513, 89519, 89521, 89527,
+ 89533, 89561, 89563, 89567, 89591, 89597, 89599, 89603, 89611, 89627,
+ 89633, 89653, 89657, 89659, 89669, 89671, 89681, 89689, 89753, 89759,
+ 89767, 89779, 89783, 89797, 89809, 89819, 89821, 89833, 89839, 89849,
+ 89867, 89891, 89897, 89899, 89909, 89917, 89923, 89939, 89959, 89963,
+ 89977, 89983, 89989, 90001, 90007, 90011, 90017, 90019, 90023, 90031,
+ 90053, 90059, 90067, 90071, 90073, 90089, 90107, 90121, 90127, 90149,
+ 90163, 90173, 90187, 90191, 90197, 90199, 90203, 90217, 90227, 90239,
+ 90247, 90263, 90271, 90281, 90289, 90313, 90353, 90359, 90371, 90373,
+ 90379, 90397, 90401, 90403, 90407, 90437, 90439, 90469, 90473, 90481,
+ 90499, 90511, 90523, 90527, 90529, 90533, 90547, 90583, 90599, 90617,
+ 90619, 90631, 90641, 90647, 90659, 90677, 90679, 90697, 90703, 90709,
+ 90731, 90749, 90787, 90793, 90803, 90821, 90823, 90833, 90841, 90847,
+ 90863, 90887, 90901, 90907, 90911, 90917, 90931, 90947, 90971, 90977,
+ 90989, 90997, 91009, 91019, 91033, 91079, 91081, 91097, 91099, 91121,
+ 91127, 91129, 91139, 91141, 91151, 91153, 91159, 91163, 91183, 91193,
+ 91199, 91229, 91237, 91243, 91249, 91253, 91283, 91291, 91297, 91303,
+ 91309, 91331, 91367, 91369, 91373, 91381, 91387, 91393, 91397, 91411,
+ 91423, 91433, 91453, 91457, 91459, 91463, 91493, 91499, 91513, 91529,
+ 91541, 91571, 91573, 91577, 91583, 91591, 91621, 91631, 91639, 91673,
+ 91691, 91703, 91711, 91733, 91753, 91757, 91771, 91781, 91801, 91807,
+ 91811, 91813, 91823, 91837, 91841, 91867, 91873, 91909, 91921, 91939,
+ 91943, 91951, 91957, 91961, 91967, 91969, 91997, 92003, 92009, 92033,
+ 92041, 92051, 92077, 92083, 92107, 92111, 92119, 92143, 92153, 92173,
+ 92177, 92179, 92189, 92203, 92219, 92221, 92227, 92233, 92237, 92243,
+ 92251, 92269, 92297, 92311, 92317, 92333, 92347, 92353, 92357, 92363,
+ 92369, 92377, 92381, 92383, 92387, 92399, 92401, 92413, 92419, 92431,
+ 92459, 92461, 92467, 92479, 92489, 92503, 92507, 92551, 92557, 92567,
+ 92569, 92581, 92593, 92623, 92627, 92639, 92641, 92647, 92657, 92669,
+ 92671, 92681, 92683, 92693, 92699, 92707, 92717, 92723, 92737, 92753,
+ 92761, 92767, 92779, 92789, 92791, 92801, 92809, 92821, 92831, 92849,
+ 92857, 92861, 92863, 92867, 92893, 92899, 92921, 92927, 92941, 92951,
+ 92957, 92959, 92987, 92993, 93001, 93047, 93053, 93059, 93077, 93083,
+ 93089, 93097, 93103, 93113, 93131, 93133, 93139, 93151, 93169, 93179,
+ 93187, 93199, 93229, 93239, 93241, 93251, 93253, 93257, 93263, 93281,
+ 93283, 93287, 93307, 93319, 93323, 93329, 93337, 93371, 93377, 93383,
+ 93407, 93419, 93427, 93463, 93479, 93481, 93487, 93491, 93493, 93497,
+ 93503, 93523, 93529, 93553, 93557, 93559, 93563, 93581, 93601, 93607,
+ 93629, 93637, 93683, 93701, 93703, 93719, 93739, 93761, 93763, 93787,
+ 93809, 93811, 93827, 93851, 93871, 93887, 93889, 93893, 93901, 93911,
+ 93913, 93923, 93937, 93941, 93949, 93967, 93971, 93979, 93983, 93997,
+ 94007, 94009, 94033, 94049, 94057, 94063, 94079, 94099, 94109, 94111,
+ 94117, 94121, 94151, 94153, 94169, 94201, 94207, 94219, 94229, 94253,
+ 94261, 94273, 94291, 94307, 94309, 94321, 94327, 94331, 94343, 94349,
+ 94351, 94379, 94397, 94399, 94421, 94427, 94433, 94439, 94441, 94447,
+ 94463, 94477, 94483, 94513, 94529, 94531, 94541, 94543, 94547, 94559,
+ 94561, 94573, 94583, 94597, 94603, 94613, 94621, 94649, 94651, 94687,
+ 94693, 94709, 94723, 94727, 94747, 94771, 94777, 94781, 94789, 94793,
+ 94811, 94819, 94823, 94837, 94841, 94847, 94849, 94873, 94889, 94903,
+ 94907, 94933, 94949, 94951, 94961, 94993, 94999, 95003, 95009, 95021,
+ 95027, 95063, 95071, 95083, 95087, 95089, 95093, 95101, 95107, 95111,
+ 95131, 95143, 95153, 95177, 95189, 95191, 95203, 95213, 95219, 95231,
+ 95233, 95239, 95257, 95261, 95267, 95273, 95279, 95287, 95311, 95317,
+ 95327, 95339, 95369, 95383, 95393, 95401, 95413, 95419, 95429, 95441,
+ 95443, 95461, 95467, 95471, 95479, 95483, 95507, 95527, 95531, 95539,
+ 95549, 95561, 95569, 95581, 95597, 95603, 95617, 95621, 95629, 95633,
+ 95651, 95701, 95707, 95713, 95717, 95723, 95731, 95737, 95747, 95773,
+ 95783, 95789, 95791, 95801, 95803, 95813, 95819, 95857, 95869, 95873,
+ 95881, 95891, 95911, 95917, 95923, 95929, 95947, 95957, 95959, 95971,
+ 95987, 95989, 96001, 96013, 96017, 96043, 96053, 96059, 96079, 96097,
+ 96137, 96149, 96157, 96167, 96179, 96181, 96199, 96211, 96221, 96223,
+ 96233, 96259, 96263, 96269, 96281, 96289, 96293, 96323, 96329, 96331,
+ 96337, 96353, 96377, 96401, 96419, 96431, 96443, 96451, 96457, 96461,
+ 96469, 96479, 96487, 96493, 96497, 96517, 96527, 96553, 96557, 96581,
+ 96587, 96589, 96601, 96643, 96661, 96667, 96671, 96697, 96703, 96731,
+ 96737, 96739, 96749, 96757, 96763, 96769, 96779, 96787, 96797, 96799,
+ 96821, 96823, 96827, 96847, 96851, 96857, 96893, 96907, 96911, 96931,
+ 96953, 96959, 96973, 96979, 96989, 96997, 97001, 97003, 97007, 97021,
+ 97039, 97073, 97081, 97103, 97117, 97127, 97151, 97157, 97159, 97169,
+ 97171, 97177, 97187, 97213, 97231, 97241, 97259, 97283, 97301, 97303,
+ 97327, 97367, 97369, 97373, 97379, 97381, 97387, 97397, 97423, 97429,
+ 97441, 97453, 97459, 97463, 97499, 97501, 97511, 97523, 97547, 97549,
+ 97553, 97561, 97571, 97577, 97579, 97583, 97607, 97609, 97613, 97649,
+ 97651, 97673, 97687, 97711, 97729, 97771, 97777, 97787, 97789, 97813,
+ 97829, 97841, 97843, 97847, 97849, 97859, 97861, 97871, 97879, 97883,
+ 97919, 97927, 97931, 97943, 97961, 97967, 97973, 97987, 98009, 98011,
+ 98017, 98041, 98047, 98057, 98081, 98101, 98123, 98129, 98143, 98179,
+ 98207, 98213, 98221, 98227, 98251, 98257, 98269, 98297, 98299, 98317,
+ 98321, 98323, 98327, 98347, 98369, 98377, 98387, 98389, 98407, 98411,
+ 98419, 98429, 98443, 98453, 98459, 98467, 98473, 98479, 98491, 98507,
+ 98519, 98533, 98543, 98561, 98563, 98573, 98597, 98621, 98627, 98639,
+ 98641, 98663, 98669, 98689, 98711, 98713, 98717, 98729, 98731, 98737,
+ 98773, 98779, 98801, 98807, 98809, 98837, 98849, 98867, 98869, 98873,
+ 98887, 98893, 98897, 98899, 98909, 98911, 98927, 98929, 98939, 98947,
+ 98953, 98963, 98981, 98993, 98999, 99013, 99017, 99023, 99041, 99053,
+ 99079, 99083, 99089, 99103, 99109, 99119, 99131, 99133, 99137, 99139,
+ 99149, 99173, 99181, 99191, 99223, 99233, 99241, 99251, 99257, 99259,
+ 99277, 99289, 99317, 99347, 99349, 99367, 99371, 99377, 99391, 99397,
+ 99401, 99409, 99431, 99439, 99469, 99487, 99497, 99523, 99527, 99529,
+ 99551, 99559, 99563, 99571, 99577, 99581, 99607, 99611, 99623, 99643,
+ 99661, 99667, 99679, 99689, 99707, 99709, 99713, 99719, 99721, 99733,
+ 99761, 99767, 99787, 99793, 99809, 99817, 99823, 99829, 99833, 99839,
+ 99859, 99871, 99877, 99881, 99901, 99907, 99923, 99929, 99961, 99971,
+ 99989, 99991, 100003, 100019, 100043, 100049, 100057, 100069, 100103, 100109,
+100129, 100151, 100153, 100169, 100183, 100189, 100193, 100207, 100213, 100237,
+100267, 100271, 100279, 100291, 100297, 100313, 100333, 100343, 100357, 100361,
+100363, 100379, 100391, 100393, 100403, 100411, 100417, 100447, 100459, 100469,
+100483, 100493, 100501, 100511, 100517, 100519, 100523, 100537, 100547, 100549,
+100559, 100591, 100609, 100613, 100621, 100649, 100669, 100673, 100693, 100699,
+100703, 100733, 100741, 100747, 100769, 100787, 100799, 100801, 100811, 100823,
+100829, 100847, 100853, 100907, 100913, 100927, 100931, 100937, 100943, 100957,
+100981, 100987, 100999, 101009, 101021, 101027, 101051, 101063, 101081, 101089,
+101107, 101111, 101113, 101117, 101119, 101141, 101149, 101159, 101161, 101173,
+101183, 101197, 101203, 101207, 101209, 101221, 101267, 101273, 101279, 101281,
+101287, 101293, 101323, 101333, 101341, 101347, 101359, 101363, 101377, 101383,
+101399, 101411, 101419, 101429, 101449, 101467, 101477, 101483, 101489, 101501,
+101503, 101513, 101527, 101531, 101533, 101537, 101561, 101573, 101581, 101599,
+101603, 101611, 101627, 101641, 101653, 101663, 101681, 101693, 101701, 101719,
+101723, 101737, 101741, 101747, 101749, 101771, 101789, 101797, 101807, 101833,
+101837, 101839, 101863, 101869, 101873, 101879, 101891, 101917, 101921, 101929,
+101939, 101957, 101963, 101977, 101987, 101999, 102001, 102013, 102019, 102023,
+102031, 102043, 102059, 102061, 102071, 102077, 102079, 102101, 102103, 102107,
+102121, 102139, 102149, 102161, 102181, 102191, 102197, 102199, 102203, 102217,
+102229, 102233, 102241, 102251, 102253, 102259, 102293, 102299, 102301, 102317,
+102329, 102337, 102359, 102367, 102397, 102407, 102409, 102433, 102437, 102451,
+102461, 102481, 102497, 102499, 102503, 102523, 102533, 102539, 102547, 102551,
+102559, 102563, 102587, 102593, 102607, 102611, 102643, 102647, 102653, 102667,
+102673, 102677, 102679, 102701, 102761, 102763, 102769, 102793, 102797, 102811,
+102829, 102841, 102859, 102871, 102877, 102881, 102911, 102913, 102929, 102931,
+102953, 102967, 102983, 103001, 103007, 103043, 103049, 103067, 103069, 103079,
+103087, 103091, 103093, 103099, 103123, 103141, 103171, 103177, 103183, 103217,
+103231, 103237, 103289, 103291, 103307, 103319, 103333, 103349, 103357, 103387,
+103391, 103393, 103399, 103409, 103421, 103423, 103451, 103457, 103471, 103483,
+103511, 103529, 103549, 103553, 103561, 103567, 103573, 103577, 103583, 103591,
+103613, 103619, 103643, 103651, 103657, 103669, 103681, 103687, 103699, 103703,
+103723, 103769, 103787, 103801, 103811, 103813, 103837, 103841, 103843, 103867,
+103889, 103903, 103913, 103919, 103951, 103963, 103967, 103969, 103979, 103981,
+103991, 103993, 103997, 104003, 104009, 104021, 104033, 104047, 104053, 104059,
+104087, 104089, 104107, 104113, 104119, 104123, 104147, 104149, 104161, 104173,
+104179, 104183, 104207, 104231, 104233, 104239, 104243, 104281, 104287, 104297,
+104309, 104311, 104323, 104327, 104347, 104369, 104381, 104383, 104393, 104399,
+104417, 104459, 104471, 104473, 104479, 104491, 104513, 104527, 104537, 104543,
+104549, 104551, 104561, 104579, 104593, 104597, 104623, 104639, 104651, 104659,
+104677, 104681, 104683, 104693, 104701, 104707, 104711, 104717, 104723, 104729,
+)
diff --git a/frozen_deps/Cryptodome/Util/number.pyi b/frozen_deps/Cryptodome/Util/number.pyi
new file mode 100644
index 0000000..f8680bf
--- /dev/null
+++ b/frozen_deps/Cryptodome/Util/number.pyi
@@ -0,0 +1,19 @@
+from typing import List, Optional, Callable
+
+
+def ceil_div(n: int, d: int) -> int: ...
+def size (N: int) -> int: ...
+def getRandomInteger(N: int, randfunc: Optional[Callable]=None) -> int: ...
+def getRandomRange(a: int, b: int, randfunc: Optional[Callable]=None) -> int: ...
+def getRandomNBitInteger(N: int, randfunc: Optional[Callable]=None) -> int: ...
+def GCD(x: int,y: int) -> int: ...
+def inverse(u: int, v: int) -> int: ...
+def getPrime(N: int, randfunc: Optional[Callable]=None) -> int: ...
+def getStrongPrime(N: int, e: Optional[int]=0, false_positive_prob: Optional[float]=1e-6, randfunc: Optional[Callable]=None) -> int: ...
+def isPrime(N: int, false_positive_prob: Optional[float]=1e-6, randfunc: Optional[Callable]=None) -> bool: ...
+def long_to_bytes(n: int, blocksize: Optional[int]=0) -> bytes: ...
+def bytes_to_long(s: bytes) -> int: ...
+def long2str(n: int, blocksize: Optional[int]=0) -> bytes: ...
+def str2long(s: bytes) -> int: ...
+
+sieve_base: List[int]
diff --git a/frozen_deps/Cryptodome/Util/py3compat.py b/frozen_deps/Cryptodome/Util/py3compat.py
new file mode 100644
index 0000000..40ef752
--- /dev/null
+++ b/frozen_deps/Cryptodome/Util/py3compat.py
@@ -0,0 +1,164 @@
+# -*- coding: utf-8 -*-
+#
+# Util/py3compat.py : Compatibility code for handling Py3k / Python 2.x
+#
+# Written in 2010 by Thorsten Behrens
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Compatibility code for handling string/bytes changes from Python 2.x to Py3k
+
+In Python 2.x, strings (of type ''str'') contain binary data, including encoded
+Unicode text (e.g. UTF-8). The separate type ''unicode'' holds Unicode text.
+Unicode literals are specified via the u'...' prefix. Indexing or slicing
+either type always produces a string of the same type as the original.
+Data read from a file is always of '''str'' type.
+
+In Python 3.x, strings (type ''str'') may only contain Unicode text. The u'...'
+prefix and the ''unicode'' type are now redundant. A new type (called
+''bytes'') has to be used for binary data (including any particular
+''encoding'' of a string). The b'...' prefix allows one to specify a binary
+literal. Indexing or slicing a string produces another string. Slicing a byte
+string produces another byte string, but the indexing operation produces an
+integer. Data read from a file is of '''str'' type if the file was opened in
+text mode, or of ''bytes'' type otherwise.
+
+Since PyCryptodome aims at supporting both Python 2.x and 3.x, the following helper
+functions are used to keep the rest of the library as independent as possible
+from the actual Python version.
+
+In general, the code should always deal with binary strings, and use integers
+instead of 1-byte character strings.
+
+b(s)
+ Take a text string literal (with no prefix or with u'...' prefix) and
+ make a byte string.
+bchr(c)
+ Take an integer and make a 1-character byte string.
+bord(c)
+ Take the result of indexing on a byte string and make an integer.
+tobytes(s)
+ Take a text string, a byte string, or a sequence of character taken from
+ a byte string and make a byte string.
+"""
+
+import sys
+import abc
+
+
+if sys.version_info[0] == 2:
+ def b(s):
+ return s
+ def bchr(s):
+ return chr(s)
+ def bstr(s):
+ return str(s)
+ def bord(s):
+ return ord(s)
+ def tobytes(s, encoding="latin-1"):
+ if isinstance(s, unicode):
+ return s.encode(encoding)
+ elif isinstance(s, str):
+ return s
+ elif isinstance(s, bytearray):
+ return bytes(s)
+ else:
+ return ''.join(s)
+ def tostr(bs):
+ return bs
+ def byte_string(s):
+ return isinstance(s, str)
+
+ # In Pyton 2.x, StringIO is a stand-alone module
+ from StringIO import StringIO as BytesIO
+
+ from sys import maxint
+
+ if sys.version_info[1] < 7:
+ import types
+ _memoryview = types.NoneType
+ else:
+ _memoryview = memoryview
+
+ iter_range = xrange
+
+ def is_native_int(x):
+ return isinstance(x, (int, long))
+
+ def is_string(x):
+ return isinstance(x, basestring)
+
+ ABC = abc.ABCMeta('ABC', (object,), {'__slots__': ()})
+
+else:
+ def b(s):
+ return s.encode("latin-1") # utf-8 would cause some side-effects we don't want
+ def bchr(s):
+ return bytes([s])
+ def bstr(s):
+ if isinstance(s,str):
+ return bytes(s,"latin-1")
+ else:
+ return bytes(s)
+ def bord(s):
+ return s
+ def tobytes(s, encoding="latin-1"):
+ if isinstance(s, bytes):
+ return s
+ elif isinstance(s, bytearray):
+ return bytes(s)
+ elif isinstance(s,str):
+ return s.encode(encoding)
+ else:
+ return bytes([s])
+ def tostr(bs):
+ return bs.decode("latin-1")
+ def byte_string(s):
+ return isinstance(s, bytes)
+
+ # In Python 3.x, StringIO is a sub-module of io
+ from io import BytesIO
+ from sys import maxsize as maxint
+
+ _memoryview = memoryview
+
+ iter_range = range
+
+ def is_native_int(x):
+ return isinstance(x, int)
+
+ def is_string(x):
+ return isinstance(x, str)
+
+ from abc import ABC
+
+
+def _copy_bytes(start, end, seq):
+ """Return an immutable copy of a sequence (byte string, byte array, memoryview)
+ in a certain interval [start:seq]"""
+
+ if isinstance(seq, _memoryview):
+ return seq[start:end].tobytes()
+ elif isinstance(seq, bytearray):
+ return bytes(seq[start:end])
+ else:
+ return seq[start:end]
+
+del sys
+del abc
diff --git a/frozen_deps/Cryptodome/Util/py3compat.pyi b/frozen_deps/Cryptodome/Util/py3compat.pyi
new file mode 100644
index 0000000..3297dc0
--- /dev/null
+++ b/frozen_deps/Cryptodome/Util/py3compat.pyi
@@ -0,0 +1,35 @@
+from typing import Union, Any, Optional, IO
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+import sys
+
+def b(s: str) -> bytes: ...
+def bchr(s: int) -> bytes: ...
+def bord(s: bytes) -> int: ...
+def tobytes(s: Union[bytes, str]) -> bytes: ...
+def tostr(b: bytes) -> str: ...
+def bytestring(x: Any) -> bool: ...
+
+def is_native_int(s: Any) -> bool: ...
+def is_string(x: Any) -> bool: ...
+
+def BytesIO(b: bytes) -> IO[bytes]: ...
+
+if sys.version_info[0] == 2:
+ from sys import maxint
+ iter_range = xrange
+
+ if sys.version_info[1] < 7:
+ import types
+ _memoryview = types.NoneType
+ else:
+ _memoryview = memoryview
+
+else:
+ from sys import maxsize as maxint
+ iter_range = range
+
+ _memoryview = memoryview
+
+def _copy_bytes(start: Optional[int], end: Optional[int], seq: Buffer) -> bytes: ...
diff --git a/frozen_deps/Cryptodome/Util/strxor.py b/frozen_deps/Cryptodome/Util/strxor.py
new file mode 100644
index 0000000..91fb4c9
--- /dev/null
+++ b/frozen_deps/Cryptodome/Util/strxor.py
@@ -0,0 +1,137 @@
+# ===================================================================
+#
+# Copyright (c) 2014, Legrandin <[email protected]>
+# 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._raw_api import (load_pycryptodome_raw_lib, c_size_t,
+ create_string_buffer, get_raw_buffer,
+ c_uint8_ptr, is_writeable_buffer)
+
+_raw_strxor = load_pycryptodome_raw_lib("Cryptodome.Util._strxor",
+ """
+ void strxor(const uint8_t *in1,
+ const uint8_t *in2,
+ uint8_t *out, size_t len);
+ void strxor_c(const uint8_t *in,
+ uint8_t c,
+ uint8_t *out,
+ size_t len);
+ """)
+
+
+def strxor(term1, term2, output=None):
+ """XOR two byte strings.
+
+ Args:
+ term1 (bytes/bytearray/memoryview):
+ The first term of the XOR operation.
+ term2 (bytes/bytearray/memoryview):
+ The second term of the XOR operation.
+ output (bytearray/memoryview):
+ The location where the result must be written to.
+ If ``None``, the result is returned.
+ :Return:
+ If ``output`` is ``None``, a new ``bytes`` string with the result.
+ Otherwise ``None``.
+ """
+
+ if len(term1) != len(term2):
+ raise ValueError("Only byte strings of equal length can be xored")
+
+ if output is None:
+ result = create_string_buffer(len(term1))
+ else:
+ # Note: output may overlap with either input
+ result = output
+
+ if not is_writeable_buffer(output):
+ raise TypeError("output must be a bytearray or a writeable memoryview")
+
+ if len(term1) != len(output):
+ raise ValueError("output must have the same length as the input"
+ " (%d bytes)" % len(term1))
+
+ _raw_strxor.strxor(c_uint8_ptr(term1),
+ c_uint8_ptr(term2),
+ c_uint8_ptr(result),
+ c_size_t(len(term1)))
+
+ if output is None:
+ return get_raw_buffer(result)
+ else:
+ return None
+
+
+def strxor_c(term, c, output=None):
+ """XOR a byte string with a repeated sequence of characters.
+
+ Args:
+ term(bytes/bytearray/memoryview):
+ The first term of the XOR operation.
+ c (bytes):
+ The byte that makes up the second term of the XOR operation.
+ output (None or bytearray/memoryview):
+ If not ``None``, the location where the result is stored into.
+
+ Return:
+ If ``output`` is ``None``, a new ``bytes`` string with the result.
+ Otherwise ``None``.
+ """
+
+ if not 0 <= c < 256:
+ raise ValueError("c must be in range(256)")
+
+ if output is None:
+ result = create_string_buffer(len(term))
+ else:
+ # Note: output may overlap with either input
+ result = output
+
+ if not is_writeable_buffer(output):
+ raise TypeError("output must be a bytearray or a writeable memoryview")
+
+ if len(term) != len(output):
+ raise ValueError("output must have the same length as the input"
+ " (%d bytes)" % len(term))
+
+ _raw_strxor.strxor_c(c_uint8_ptr(term),
+ c,
+ c_uint8_ptr(result),
+ c_size_t(len(term))
+ )
+
+ if output is None:
+ return get_raw_buffer(result)
+ else:
+ return None
+
+
+def _strxor_direct(term1, term2, result):
+ """Very fast XOR - check conditions!"""
+ _raw_strxor.strxor(term1, term2, result, c_size_t(len(term1)))
+
diff --git a/frozen_deps/Cryptodome/Util/strxor.pyi b/frozen_deps/Cryptodome/Util/strxor.pyi
new file mode 100644
index 0000000..ca896f3
--- /dev/null
+++ b/frozen_deps/Cryptodome/Util/strxor.pyi
@@ -0,0 +1,6 @@
+from typing import Union, Optional
+
+Buffer = Union[bytes, bytearray, memoryview]
+
+def strxor(term1: bytes, term2: bytes, output: Optional[Buffer]=...) -> bytes: ...
+def strxor_c(term: bytes, c: int, output: Optional[Buffer]=...) -> bytes: ...
diff --git a/frozen_deps/Cryptodome/__init__.py b/frozen_deps/Cryptodome/__init__.py
new file mode 100644
index 0000000..bb08e39
--- /dev/null
+++ b/frozen_deps/Cryptodome/__init__.py
@@ -0,0 +1,6 @@
+__all__ = ['Cipher', 'Hash', 'Protocol', 'PublicKey', 'Util', 'Signature',
+ 'IO', 'Math']
+
+version_info = (3, 9, '9')
+
+__version__ = ".".join([str(x) for x in version_info])
diff --git a/frozen_deps/Cryptodome/__init__.pyi b/frozen_deps/Cryptodome/__init__.pyi
new file mode 100644
index 0000000..bc73446
--- /dev/null
+++ b/frozen_deps/Cryptodome/__init__.pyi
@@ -0,0 +1,4 @@
+from typing import Tuple, Union
+
+version_info : Tuple[int, int, Union[int, str]]
+__version__ : str
diff --git a/frozen_deps/Cryptodome/py.typed b/frozen_deps/Cryptodome/py.typed
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/frozen_deps/Cryptodome/py.typed