aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/nacl/bindings
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/nacl/bindings')
-rw-r--r--.venv/lib/python3.12/site-packages/nacl/bindings/__init__.py451
-rw-r--r--.venv/lib/python3.12/site-packages/nacl/bindings/crypto_aead.py559
-rw-r--r--.venv/lib/python3.12/site-packages/nacl/bindings/crypto_box.py324
-rw-r--r--.venv/lib/python3.12/site-packages/nacl/bindings/crypto_core.py412
-rw-r--r--.venv/lib/python3.12/site-packages/nacl/bindings/crypto_generichash.py281
-rw-r--r--.venv/lib/python3.12/site-packages/nacl/bindings/crypto_hash.py63
-rw-r--r--.venv/lib/python3.12/site-packages/nacl/bindings/crypto_kx.py200
-rw-r--r--.venv/lib/python3.12/site-packages/nacl/bindings/crypto_pwhash.py600
-rw-r--r--.venv/lib/python3.12/site-packages/nacl/bindings/crypto_scalarmult.py240
-rw-r--r--.venv/lib/python3.12/site-packages/nacl/bindings/crypto_secretbox.py86
-rw-r--r--.venv/lib/python3.12/site-packages/nacl/bindings/crypto_secretstream.py357
-rw-r--r--.venv/lib/python3.12/site-packages/nacl/bindings/crypto_shorthash.py81
-rw-r--r--.venv/lib/python3.12/site-packages/nacl/bindings/crypto_sign.py327
-rw-r--r--.venv/lib/python3.12/site-packages/nacl/bindings/randombytes.py51
-rw-r--r--.venv/lib/python3.12/site-packages/nacl/bindings/sodium_core.py33
-rw-r--r--.venv/lib/python3.12/site-packages/nacl/bindings/utils.py141
16 files changed, 4206 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/nacl/bindings/__init__.py b/.venv/lib/python3.12/site-packages/nacl/bindings/__init__.py
new file mode 100644
index 00000000..1e3b10e8
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/nacl/bindings/__init__.py
@@ -0,0 +1,451 @@
+# Copyright 2013-2019 Donald Stufft and individual contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+from nacl.bindings.crypto_aead import (
+ crypto_aead_chacha20poly1305_ABYTES,
+ crypto_aead_chacha20poly1305_KEYBYTES,
+ crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX,
+ crypto_aead_chacha20poly1305_NPUBBYTES,
+ crypto_aead_chacha20poly1305_NSECBYTES,
+ crypto_aead_chacha20poly1305_decrypt,
+ crypto_aead_chacha20poly1305_encrypt,
+ crypto_aead_chacha20poly1305_ietf_ABYTES,
+ crypto_aead_chacha20poly1305_ietf_KEYBYTES,
+ crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX,
+ crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
+ crypto_aead_chacha20poly1305_ietf_NSECBYTES,
+ crypto_aead_chacha20poly1305_ietf_decrypt,
+ crypto_aead_chacha20poly1305_ietf_encrypt,
+ crypto_aead_xchacha20poly1305_ietf_ABYTES,
+ crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
+ crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX,
+ crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
+ crypto_aead_xchacha20poly1305_ietf_NSECBYTES,
+ crypto_aead_xchacha20poly1305_ietf_decrypt,
+ crypto_aead_xchacha20poly1305_ietf_encrypt,
+)
+from nacl.bindings.crypto_box import (
+ crypto_box,
+ crypto_box_BEFORENMBYTES,
+ crypto_box_BOXZEROBYTES,
+ crypto_box_NONCEBYTES,
+ crypto_box_PUBLICKEYBYTES,
+ crypto_box_SEALBYTES,
+ crypto_box_SECRETKEYBYTES,
+ crypto_box_SEEDBYTES,
+ crypto_box_ZEROBYTES,
+ crypto_box_afternm,
+ crypto_box_beforenm,
+ crypto_box_keypair,
+ crypto_box_open,
+ crypto_box_open_afternm,
+ crypto_box_seal,
+ crypto_box_seal_open,
+ crypto_box_seed_keypair,
+)
+from nacl.bindings.crypto_core import (
+ crypto_core_ed25519_BYTES,
+ crypto_core_ed25519_NONREDUCEDSCALARBYTES,
+ crypto_core_ed25519_SCALARBYTES,
+ crypto_core_ed25519_add,
+ crypto_core_ed25519_is_valid_point,
+ crypto_core_ed25519_scalar_add,
+ crypto_core_ed25519_scalar_complement,
+ crypto_core_ed25519_scalar_invert,
+ crypto_core_ed25519_scalar_mul,
+ crypto_core_ed25519_scalar_negate,
+ crypto_core_ed25519_scalar_reduce,
+ crypto_core_ed25519_scalar_sub,
+ crypto_core_ed25519_sub,
+ has_crypto_core_ed25519,
+)
+from nacl.bindings.crypto_generichash import (
+ crypto_generichash_BYTES,
+ crypto_generichash_BYTES_MAX,
+ crypto_generichash_BYTES_MIN,
+ crypto_generichash_KEYBYTES,
+ crypto_generichash_KEYBYTES_MAX,
+ crypto_generichash_KEYBYTES_MIN,
+ crypto_generichash_PERSONALBYTES,
+ crypto_generichash_SALTBYTES,
+ crypto_generichash_STATEBYTES,
+ generichash_blake2b_final as crypto_generichash_blake2b_final,
+ generichash_blake2b_init as crypto_generichash_blake2b_init,
+ generichash_blake2b_salt_personal as crypto_generichash_blake2b_salt_personal,
+ generichash_blake2b_update as crypto_generichash_blake2b_update,
+)
+from nacl.bindings.crypto_hash import (
+ crypto_hash,
+ crypto_hash_BYTES,
+ crypto_hash_sha256,
+ crypto_hash_sha256_BYTES,
+ crypto_hash_sha512,
+ crypto_hash_sha512_BYTES,
+)
+from nacl.bindings.crypto_kx import (
+ crypto_kx_PUBLIC_KEY_BYTES,
+ crypto_kx_SECRET_KEY_BYTES,
+ crypto_kx_SEED_BYTES,
+ crypto_kx_SESSION_KEY_BYTES,
+ crypto_kx_client_session_keys,
+ crypto_kx_keypair,
+ crypto_kx_seed_keypair,
+ crypto_kx_server_session_keys,
+)
+from nacl.bindings.crypto_pwhash import (
+ crypto_pwhash_ALG_ARGON2I13,
+ crypto_pwhash_ALG_ARGON2ID13,
+ crypto_pwhash_ALG_DEFAULT,
+ crypto_pwhash_BYTES_MAX,
+ crypto_pwhash_BYTES_MIN,
+ crypto_pwhash_PASSWD_MAX,
+ crypto_pwhash_PASSWD_MIN,
+ crypto_pwhash_SALTBYTES,
+ crypto_pwhash_STRBYTES,
+ crypto_pwhash_alg,
+ crypto_pwhash_argon2i_MEMLIMIT_INTERACTIVE,
+ crypto_pwhash_argon2i_MEMLIMIT_MAX,
+ crypto_pwhash_argon2i_MEMLIMIT_MIN,
+ crypto_pwhash_argon2i_MEMLIMIT_MODERATE,
+ crypto_pwhash_argon2i_MEMLIMIT_SENSITIVE,
+ crypto_pwhash_argon2i_OPSLIMIT_INTERACTIVE,
+ crypto_pwhash_argon2i_OPSLIMIT_MAX,
+ crypto_pwhash_argon2i_OPSLIMIT_MIN,
+ crypto_pwhash_argon2i_OPSLIMIT_MODERATE,
+ crypto_pwhash_argon2i_OPSLIMIT_SENSITIVE,
+ crypto_pwhash_argon2i_STRPREFIX,
+ crypto_pwhash_argon2id_MEMLIMIT_INTERACTIVE,
+ crypto_pwhash_argon2id_MEMLIMIT_MAX,
+ crypto_pwhash_argon2id_MEMLIMIT_MIN,
+ crypto_pwhash_argon2id_MEMLIMIT_MODERATE,
+ crypto_pwhash_argon2id_MEMLIMIT_SENSITIVE,
+ crypto_pwhash_argon2id_OPSLIMIT_INTERACTIVE,
+ crypto_pwhash_argon2id_OPSLIMIT_MAX,
+ crypto_pwhash_argon2id_OPSLIMIT_MIN,
+ crypto_pwhash_argon2id_OPSLIMIT_MODERATE,
+ crypto_pwhash_argon2id_OPSLIMIT_SENSITIVE,
+ crypto_pwhash_argon2id_STRPREFIX,
+ crypto_pwhash_scryptsalsa208sha256_BYTES_MAX,
+ crypto_pwhash_scryptsalsa208sha256_BYTES_MIN,
+ crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE,
+ crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
+ crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
+ crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE,
+ crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE,
+ crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
+ crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
+ crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE,
+ crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX,
+ crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN,
+ crypto_pwhash_scryptsalsa208sha256_SALTBYTES,
+ crypto_pwhash_scryptsalsa208sha256_STRBYTES,
+ crypto_pwhash_scryptsalsa208sha256_STRPREFIX,
+ crypto_pwhash_scryptsalsa208sha256_ll,
+ crypto_pwhash_scryptsalsa208sha256_str,
+ crypto_pwhash_scryptsalsa208sha256_str_verify,
+ crypto_pwhash_str_alg,
+ crypto_pwhash_str_verify,
+ has_crypto_pwhash_scryptsalsa208sha256,
+ nacl_bindings_pick_scrypt_params,
+)
+from nacl.bindings.crypto_scalarmult import (
+ crypto_scalarmult,
+ crypto_scalarmult_BYTES,
+ crypto_scalarmult_SCALARBYTES,
+ crypto_scalarmult_base,
+ crypto_scalarmult_ed25519,
+ crypto_scalarmult_ed25519_BYTES,
+ crypto_scalarmult_ed25519_SCALARBYTES,
+ crypto_scalarmult_ed25519_base,
+ crypto_scalarmult_ed25519_base_noclamp,
+ crypto_scalarmult_ed25519_noclamp,
+ has_crypto_scalarmult_ed25519,
+)
+from nacl.bindings.crypto_secretbox import (
+ crypto_secretbox,
+ crypto_secretbox_BOXZEROBYTES,
+ crypto_secretbox_KEYBYTES,
+ crypto_secretbox_MACBYTES,
+ crypto_secretbox_MESSAGEBYTES_MAX,
+ crypto_secretbox_NONCEBYTES,
+ crypto_secretbox_ZEROBYTES,
+ crypto_secretbox_open,
+)
+from nacl.bindings.crypto_secretstream import (
+ crypto_secretstream_xchacha20poly1305_ABYTES,
+ crypto_secretstream_xchacha20poly1305_HEADERBYTES,
+ crypto_secretstream_xchacha20poly1305_KEYBYTES,
+ crypto_secretstream_xchacha20poly1305_STATEBYTES,
+ crypto_secretstream_xchacha20poly1305_TAG_FINAL,
+ crypto_secretstream_xchacha20poly1305_TAG_MESSAGE,
+ crypto_secretstream_xchacha20poly1305_TAG_PUSH,
+ crypto_secretstream_xchacha20poly1305_TAG_REKEY,
+ crypto_secretstream_xchacha20poly1305_init_pull,
+ crypto_secretstream_xchacha20poly1305_init_push,
+ crypto_secretstream_xchacha20poly1305_keygen,
+ crypto_secretstream_xchacha20poly1305_pull,
+ crypto_secretstream_xchacha20poly1305_push,
+ crypto_secretstream_xchacha20poly1305_rekey,
+ crypto_secretstream_xchacha20poly1305_state,
+)
+from nacl.bindings.crypto_shorthash import (
+ BYTES as crypto_shorthash_siphash24_BYTES,
+ KEYBYTES as crypto_shorthash_siphash24_KEYBYTES,
+ XBYTES as crypto_shorthash_siphashx24_BYTES,
+ XKEYBYTES as crypto_shorthash_siphashx24_KEYBYTES,
+ crypto_shorthash_siphash24,
+ crypto_shorthash_siphashx24,
+ has_crypto_shorthash_siphashx24,
+)
+from nacl.bindings.crypto_sign import (
+ crypto_sign,
+ crypto_sign_BYTES,
+ crypto_sign_PUBLICKEYBYTES,
+ crypto_sign_SECRETKEYBYTES,
+ crypto_sign_SEEDBYTES,
+ crypto_sign_ed25519_pk_to_curve25519,
+ crypto_sign_ed25519_sk_to_curve25519,
+ crypto_sign_ed25519_sk_to_pk,
+ crypto_sign_ed25519_sk_to_seed,
+ crypto_sign_ed25519ph_STATEBYTES,
+ crypto_sign_ed25519ph_final_create,
+ crypto_sign_ed25519ph_final_verify,
+ crypto_sign_ed25519ph_state,
+ crypto_sign_ed25519ph_update,
+ crypto_sign_keypair,
+ crypto_sign_open,
+ crypto_sign_seed_keypair,
+)
+from nacl.bindings.randombytes import (
+ randombytes,
+ randombytes_buf_deterministic,
+)
+from nacl.bindings.sodium_core import sodium_init
+from nacl.bindings.utils import (
+ sodium_add,
+ sodium_increment,
+ sodium_memcmp,
+ sodium_pad,
+ sodium_unpad,
+)
+
+
+__all__ = [
+ "crypto_aead_chacha20poly1305_ABYTES",
+ "crypto_aead_chacha20poly1305_KEYBYTES",
+ "crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX",
+ "crypto_aead_chacha20poly1305_NPUBBYTES",
+ "crypto_aead_chacha20poly1305_NSECBYTES",
+ "crypto_aead_chacha20poly1305_decrypt",
+ "crypto_aead_chacha20poly1305_encrypt",
+ "crypto_aead_chacha20poly1305_ietf_ABYTES",
+ "crypto_aead_chacha20poly1305_ietf_KEYBYTES",
+ "crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX",
+ "crypto_aead_chacha20poly1305_ietf_NPUBBYTES",
+ "crypto_aead_chacha20poly1305_ietf_NSECBYTES",
+ "crypto_aead_chacha20poly1305_ietf_decrypt",
+ "crypto_aead_chacha20poly1305_ietf_encrypt",
+ "crypto_aead_xchacha20poly1305_ietf_ABYTES",
+ "crypto_aead_xchacha20poly1305_ietf_KEYBYTES",
+ "crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX",
+ "crypto_aead_xchacha20poly1305_ietf_NPUBBYTES",
+ "crypto_aead_xchacha20poly1305_ietf_NSECBYTES",
+ "crypto_aead_xchacha20poly1305_ietf_decrypt",
+ "crypto_aead_xchacha20poly1305_ietf_encrypt",
+ "crypto_box_SECRETKEYBYTES",
+ "crypto_box_PUBLICKEYBYTES",
+ "crypto_box_SEEDBYTES",
+ "crypto_box_NONCEBYTES",
+ "crypto_box_ZEROBYTES",
+ "crypto_box_BOXZEROBYTES",
+ "crypto_box_BEFORENMBYTES",
+ "crypto_box_SEALBYTES",
+ "crypto_box_keypair",
+ "crypto_box",
+ "crypto_box_open",
+ "crypto_box_beforenm",
+ "crypto_box_afternm",
+ "crypto_box_open_afternm",
+ "crypto_box_seal",
+ "crypto_box_seal_open",
+ "crypto_box_seed_keypair",
+ "has_crypto_core_ed25519",
+ "crypto_core_ed25519_BYTES",
+ "crypto_core_ed25519_UNIFORMBYTES",
+ "crypto_core_ed25519_SCALARBYTES",
+ "crypto_core_ed25519_NONREDUCEDSCALARBYTES",
+ "crypto_core_ed25519_add",
+ "crypto_core_ed25519_from_uniform",
+ "crypto_core_ed25519_is_valid_point",
+ "crypto_core_ed25519_sub",
+ "crypto_core_ed25519_scalar_invert",
+ "crypto_core_ed25519_scalar_negate",
+ "crypto_core_ed25519_scalar_complement",
+ "crypto_core_ed25519_scalar_add",
+ "crypto_core_ed25519_scalar_sub",
+ "crypto_core_ed25519_scalar_mul",
+ "crypto_core_ed25519_scalar_reduce",
+ "crypto_hash_BYTES",
+ "crypto_hash_sha256_BYTES",
+ "crypto_hash_sha512_BYTES",
+ "crypto_hash",
+ "crypto_hash_sha256",
+ "crypto_hash_sha512",
+ "crypto_generichash_BYTES",
+ "crypto_generichash_BYTES_MIN",
+ "crypto_generichash_BYTES_MAX",
+ "crypto_generichash_KEYBYTES",
+ "crypto_generichash_KEYBYTES_MIN",
+ "crypto_generichash_KEYBYTES_MAX",
+ "crypto_generichash_SALTBYTES",
+ "crypto_generichash_PERSONALBYTES",
+ "crypto_generichash_STATEBYTES",
+ "crypto_generichash_blake2b_salt_personal",
+ "crypto_generichash_blake2b_init",
+ "crypto_generichash_blake2b_update",
+ "crypto_generichash_blake2b_final",
+ "crypto_kx_keypair",
+ "crypto_kx_seed_keypair",
+ "crypto_kx_client_session_keys",
+ "crypto_kx_server_session_keys",
+ "crypto_kx_PUBLIC_KEY_BYTES",
+ "crypto_kx_SECRET_KEY_BYTES",
+ "crypto_kx_SEED_BYTES",
+ "crypto_kx_SESSION_KEY_BYTES",
+ "has_crypto_scalarmult_ed25519",
+ "crypto_scalarmult_BYTES",
+ "crypto_scalarmult_SCALARBYTES",
+ "crypto_scalarmult",
+ "crypto_scalarmult_base",
+ "crypto_scalarmult_ed25519_BYTES",
+ "crypto_scalarmult_ed25519_SCALARBYTES",
+ "crypto_scalarmult_ed25519",
+ "crypto_scalarmult_ed25519_base",
+ "crypto_scalarmult_ed25519_noclamp",
+ "crypto_scalarmult_ed25519_base_noclamp",
+ "crypto_secretbox_KEYBYTES",
+ "crypto_secretbox_NONCEBYTES",
+ "crypto_secretbox_ZEROBYTES",
+ "crypto_secretbox_BOXZEROBYTES",
+ "crypto_secretbox_MACBYTES",
+ "crypto_secretbox_MESSAGEBYTES_MAX",
+ "crypto_secretbox",
+ "crypto_secretbox_open",
+ "crypto_secretstream_xchacha20poly1305_ABYTES",
+ "crypto_secretstream_xchacha20poly1305_HEADERBYTES",
+ "crypto_secretstream_xchacha20poly1305_KEYBYTES",
+ "crypto_secretstream_xchacha20poly1305_STATEBYTES",
+ "crypto_secretstream_xchacha20poly1305_TAG_FINAL",
+ "crypto_secretstream_xchacha20poly1305_TAG_MESSAGE",
+ "crypto_secretstream_xchacha20poly1305_TAG_PUSH",
+ "crypto_secretstream_xchacha20poly1305_TAG_REKEY",
+ "crypto_secretstream_xchacha20poly1305_init_pull",
+ "crypto_secretstream_xchacha20poly1305_init_push",
+ "crypto_secretstream_xchacha20poly1305_keygen",
+ "crypto_secretstream_xchacha20poly1305_pull",
+ "crypto_secretstream_xchacha20poly1305_push",
+ "crypto_secretstream_xchacha20poly1305_rekey",
+ "crypto_secretstream_xchacha20poly1305_state",
+ "has_crypto_shorthash_siphashx24",
+ "crypto_shorthash_siphash24_BYTES",
+ "crypto_shorthash_siphash24_KEYBYTES",
+ "crypto_shorthash_siphash24",
+ "crypto_shorthash_siphashx24_BYTES",
+ "crypto_shorthash_siphashx24_KEYBYTES",
+ "crypto_shorthash_siphashx24",
+ "crypto_sign_BYTES",
+ "crypto_sign_SEEDBYTES",
+ "crypto_sign_PUBLICKEYBYTES",
+ "crypto_sign_SECRETKEYBYTES",
+ "crypto_sign_keypair",
+ "crypto_sign_seed_keypair",
+ "crypto_sign",
+ "crypto_sign_open",
+ "crypto_sign_ed25519_pk_to_curve25519",
+ "crypto_sign_ed25519_sk_to_curve25519",
+ "crypto_sign_ed25519_sk_to_pk",
+ "crypto_sign_ed25519_sk_to_seed",
+ "crypto_sign_ed25519ph_STATEBYTES",
+ "crypto_sign_ed25519ph_final_create",
+ "crypto_sign_ed25519ph_final_verify",
+ "crypto_sign_ed25519ph_state",
+ "crypto_sign_ed25519ph_update",
+ "crypto_pwhash_ALG_ARGON2I13",
+ "crypto_pwhash_ALG_ARGON2ID13",
+ "crypto_pwhash_ALG_DEFAULT",
+ "crypto_pwhash_BYTES_MAX",
+ "crypto_pwhash_BYTES_MIN",
+ "crypto_pwhash_PASSWD_MAX",
+ "crypto_pwhash_PASSWD_MIN",
+ "crypto_pwhash_SALTBYTES",
+ "crypto_pwhash_STRBYTES",
+ "crypto_pwhash_alg",
+ "crypto_pwhash_argon2i_MEMLIMIT_MIN",
+ "crypto_pwhash_argon2i_MEMLIMIT_MAX",
+ "crypto_pwhash_argon2i_MEMLIMIT_INTERACTIVE",
+ "crypto_pwhash_argon2i_MEMLIMIT_MODERATE",
+ "crypto_pwhash_argon2i_MEMLIMIT_SENSITIVE",
+ "crypto_pwhash_argon2i_OPSLIMIT_MIN",
+ "crypto_pwhash_argon2i_OPSLIMIT_MAX",
+ "crypto_pwhash_argon2i_OPSLIMIT_INTERACTIVE",
+ "crypto_pwhash_argon2i_OPSLIMIT_MODERATE",
+ "crypto_pwhash_argon2i_OPSLIMIT_SENSITIVE",
+ "crypto_pwhash_argon2i_STRPREFIX",
+ "crypto_pwhash_argon2id_MEMLIMIT_MIN",
+ "crypto_pwhash_argon2id_MEMLIMIT_MAX",
+ "crypto_pwhash_argon2id_MEMLIMIT_INTERACTIVE",
+ "crypto_pwhash_argon2id_MEMLIMIT_MODERATE",
+ "crypto_pwhash_argon2id_OPSLIMIT_MIN",
+ "crypto_pwhash_argon2id_OPSLIMIT_MAX",
+ "crypto_pwhash_argon2id_MEMLIMIT_SENSITIVE",
+ "crypto_pwhash_argon2id_OPSLIMIT_INTERACTIVE",
+ "crypto_pwhash_argon2id_OPSLIMIT_MODERATE",
+ "crypto_pwhash_argon2id_OPSLIMIT_SENSITIVE",
+ "crypto_pwhash_argon2id_STRPREFIX",
+ "crypto_pwhash_str_alg",
+ "crypto_pwhash_str_verify",
+ "has_crypto_pwhash_scryptsalsa208sha256",
+ "crypto_pwhash_scryptsalsa208sha256_BYTES_MAX",
+ "crypto_pwhash_scryptsalsa208sha256_BYTES_MIN",
+ "crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE",
+ "crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX",
+ "crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN",
+ "crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE",
+ "crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE",
+ "crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX",
+ "crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN",
+ "crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE",
+ "crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX",
+ "crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN",
+ "crypto_pwhash_scryptsalsa208sha256_SALTBYTES",
+ "crypto_pwhash_scryptsalsa208sha256_STRBYTES",
+ "crypto_pwhash_scryptsalsa208sha256_STRPREFIX",
+ "crypto_pwhash_scryptsalsa208sha256_ll",
+ "crypto_pwhash_scryptsalsa208sha256_str",
+ "crypto_pwhash_scryptsalsa208sha256_str_verify",
+ "nacl_bindings_pick_scrypt_params",
+ "randombytes",
+ "randombytes_buf_deterministic",
+ "sodium_init",
+ "sodium_add",
+ "sodium_increment",
+ "sodium_memcmp",
+ "sodium_pad",
+ "sodium_unpad",
+]
+
+
+# Initialize Sodium
+sodium_init()
diff --git a/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_aead.py b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_aead.py
new file mode 100644
index 00000000..2e7168db
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_aead.py
@@ -0,0 +1,559 @@
+# Copyright 2017 Donald Stufft and individual contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from typing import Optional
+
+from nacl import exceptions as exc
+from nacl._sodium import ffi, lib
+from nacl.exceptions import ensure
+
+"""
+Implementations of authenticated encription with associated data (*AEAD*)
+constructions building on the chacha20 stream cipher and the poly1305
+authenticator
+"""
+
+crypto_aead_chacha20poly1305_ietf_KEYBYTES: int = (
+ lib.crypto_aead_chacha20poly1305_ietf_keybytes()
+)
+crypto_aead_chacha20poly1305_ietf_NSECBYTES: int = (
+ lib.crypto_aead_chacha20poly1305_ietf_nsecbytes()
+)
+crypto_aead_chacha20poly1305_ietf_NPUBBYTES: int = (
+ lib.crypto_aead_chacha20poly1305_ietf_npubbytes()
+)
+crypto_aead_chacha20poly1305_ietf_ABYTES: int = (
+ lib.crypto_aead_chacha20poly1305_ietf_abytes()
+)
+crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX: int = (
+ lib.crypto_aead_chacha20poly1305_ietf_messagebytes_max()
+)
+_aead_chacha20poly1305_ietf_CRYPTBYTES_MAX = (
+ crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX
+ + crypto_aead_chacha20poly1305_ietf_ABYTES
+)
+
+crypto_aead_chacha20poly1305_KEYBYTES: int = (
+ lib.crypto_aead_chacha20poly1305_keybytes()
+)
+crypto_aead_chacha20poly1305_NSECBYTES: int = (
+ lib.crypto_aead_chacha20poly1305_nsecbytes()
+)
+crypto_aead_chacha20poly1305_NPUBBYTES: int = (
+ lib.crypto_aead_chacha20poly1305_npubbytes()
+)
+crypto_aead_chacha20poly1305_ABYTES: int = (
+ lib.crypto_aead_chacha20poly1305_abytes()
+)
+crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX: int = (
+ lib.crypto_aead_chacha20poly1305_messagebytes_max()
+)
+_aead_chacha20poly1305_CRYPTBYTES_MAX = (
+ crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX
+ + crypto_aead_chacha20poly1305_ABYTES
+)
+
+crypto_aead_xchacha20poly1305_ietf_KEYBYTES: int = (
+ lib.crypto_aead_xchacha20poly1305_ietf_keybytes()
+)
+crypto_aead_xchacha20poly1305_ietf_NSECBYTES: int = (
+ lib.crypto_aead_xchacha20poly1305_ietf_nsecbytes()
+)
+crypto_aead_xchacha20poly1305_ietf_NPUBBYTES: int = (
+ lib.crypto_aead_xchacha20poly1305_ietf_npubbytes()
+)
+crypto_aead_xchacha20poly1305_ietf_ABYTES: int = (
+ lib.crypto_aead_xchacha20poly1305_ietf_abytes()
+)
+crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX: int = (
+ lib.crypto_aead_xchacha20poly1305_ietf_messagebytes_max()
+)
+_aead_xchacha20poly1305_ietf_CRYPTBYTES_MAX = (
+ crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX
+ + crypto_aead_xchacha20poly1305_ietf_ABYTES
+)
+
+
+def crypto_aead_chacha20poly1305_ietf_encrypt(
+ message: bytes, aad: Optional[bytes], nonce: bytes, key: bytes
+) -> bytes:
+ """
+ Encrypt the given ``message`` using the IETF ratified chacha20poly1305
+ construction described in RFC7539.
+
+ :param message:
+ :type message: bytes
+ :param aad:
+ :type aad: Optional[bytes]
+ :param nonce:
+ :type nonce: bytes
+ :param key:
+ :type key: bytes
+ :return: authenticated ciphertext
+ :rtype: bytes
+ """
+ ensure(
+ isinstance(message, bytes),
+ "Input message type must be bytes",
+ raising=exc.TypeError,
+ )
+
+ mlen = len(message)
+
+ ensure(
+ mlen <= crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX,
+ "Message must be at most {} bytes long".format(
+ crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX
+ ),
+ raising=exc.ValueError,
+ )
+
+ ensure(
+ isinstance(aad, bytes) or (aad is None),
+ "Additional data must be bytes or None",
+ raising=exc.TypeError,
+ )
+
+ ensure(
+ isinstance(nonce, bytes)
+ and len(nonce) == crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
+ "Nonce must be a {} bytes long bytes sequence".format(
+ crypto_aead_chacha20poly1305_ietf_NPUBBYTES
+ ),
+ raising=exc.TypeError,
+ )
+
+ ensure(
+ isinstance(key, bytes)
+ and len(key) == crypto_aead_chacha20poly1305_ietf_KEYBYTES,
+ "Key must be a {} bytes long bytes sequence".format(
+ crypto_aead_chacha20poly1305_ietf_KEYBYTES
+ ),
+ raising=exc.TypeError,
+ )
+
+ if aad:
+ _aad = aad
+ aalen = len(aad)
+ else:
+ _aad = ffi.NULL
+ aalen = 0
+
+ mxout = mlen + crypto_aead_chacha20poly1305_ietf_ABYTES
+
+ clen = ffi.new("unsigned long long *")
+
+ ciphertext = ffi.new("unsigned char[]", mxout)
+
+ res = lib.crypto_aead_chacha20poly1305_ietf_encrypt(
+ ciphertext, clen, message, mlen, _aad, aalen, ffi.NULL, nonce, key
+ )
+
+ ensure(res == 0, "Encryption failed.", raising=exc.CryptoError)
+ return ffi.buffer(ciphertext, clen[0])[:]
+
+
+def crypto_aead_chacha20poly1305_ietf_decrypt(
+ ciphertext: bytes, aad: Optional[bytes], nonce: bytes, key: bytes
+) -> bytes:
+ """
+ Decrypt the given ``ciphertext`` using the IETF ratified chacha20poly1305
+ construction described in RFC7539.
+
+ :param ciphertext:
+ :type ciphertext: bytes
+ :param aad:
+ :type aad: Optional[bytes]
+ :param nonce:
+ :type nonce: bytes
+ :param key:
+ :type key: bytes
+ :return: message
+ :rtype: bytes
+ """
+ ensure(
+ isinstance(ciphertext, bytes),
+ "Input ciphertext type must be bytes",
+ raising=exc.TypeError,
+ )
+
+ clen = len(ciphertext)
+
+ ensure(
+ clen <= _aead_chacha20poly1305_ietf_CRYPTBYTES_MAX,
+ "Ciphertext must be at most {} bytes long".format(
+ _aead_chacha20poly1305_ietf_CRYPTBYTES_MAX
+ ),
+ raising=exc.ValueError,
+ )
+
+ ensure(
+ isinstance(aad, bytes) or (aad is None),
+ "Additional data must be bytes or None",
+ raising=exc.TypeError,
+ )
+
+ ensure(
+ isinstance(nonce, bytes)
+ and len(nonce) == crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
+ "Nonce must be a {} bytes long bytes sequence".format(
+ crypto_aead_chacha20poly1305_ietf_NPUBBYTES
+ ),
+ raising=exc.TypeError,
+ )
+
+ ensure(
+ isinstance(key, bytes)
+ and len(key) == crypto_aead_chacha20poly1305_ietf_KEYBYTES,
+ "Key must be a {} bytes long bytes sequence".format(
+ crypto_aead_chacha20poly1305_ietf_KEYBYTES
+ ),
+ raising=exc.TypeError,
+ )
+
+ mxout = clen - crypto_aead_chacha20poly1305_ietf_ABYTES
+
+ mlen = ffi.new("unsigned long long *")
+ message = ffi.new("unsigned char[]", mxout)
+
+ if aad:
+ _aad = aad
+ aalen = len(aad)
+ else:
+ _aad = ffi.NULL
+ aalen = 0
+
+ res = lib.crypto_aead_chacha20poly1305_ietf_decrypt(
+ message, mlen, ffi.NULL, ciphertext, clen, _aad, aalen, nonce, key
+ )
+
+ ensure(res == 0, "Decryption failed.", raising=exc.CryptoError)
+
+ return ffi.buffer(message, mlen[0])[:]
+
+
+def crypto_aead_chacha20poly1305_encrypt(
+ message: bytes, aad: Optional[bytes], nonce: bytes, key: bytes
+) -> bytes:
+ """
+ Encrypt the given ``message`` using the "legacy" construction
+ described in draft-agl-tls-chacha20poly1305.
+
+ :param message:
+ :type message: bytes
+ :param aad:
+ :type aad: Optional[bytes]
+ :param nonce:
+ :type nonce: bytes
+ :param key:
+ :type key: bytes
+ :return: authenticated ciphertext
+ :rtype: bytes
+ """
+ ensure(
+ isinstance(message, bytes),
+ "Input message type must be bytes",
+ raising=exc.TypeError,
+ )
+
+ mlen = len(message)
+
+ ensure(
+ mlen <= crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX,
+ "Message must be at most {} bytes long".format(
+ crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX
+ ),
+ raising=exc.ValueError,
+ )
+
+ ensure(
+ isinstance(aad, bytes) or (aad is None),
+ "Additional data must be bytes or None",
+ raising=exc.TypeError,
+ )
+
+ ensure(
+ isinstance(nonce, bytes)
+ and len(nonce) == crypto_aead_chacha20poly1305_NPUBBYTES,
+ "Nonce must be a {} bytes long bytes sequence".format(
+ crypto_aead_chacha20poly1305_NPUBBYTES
+ ),
+ raising=exc.TypeError,
+ )
+
+ ensure(
+ isinstance(key, bytes)
+ and len(key) == crypto_aead_chacha20poly1305_KEYBYTES,
+ "Key must be a {} bytes long bytes sequence".format(
+ crypto_aead_chacha20poly1305_KEYBYTES
+ ),
+ raising=exc.TypeError,
+ )
+
+ if aad:
+ _aad = aad
+ aalen = len(aad)
+ else:
+ _aad = ffi.NULL
+ aalen = 0
+
+ mlen = len(message)
+ mxout = mlen + crypto_aead_chacha20poly1305_ietf_ABYTES
+
+ clen = ffi.new("unsigned long long *")
+
+ ciphertext = ffi.new("unsigned char[]", mxout)
+
+ res = lib.crypto_aead_chacha20poly1305_encrypt(
+ ciphertext, clen, message, mlen, _aad, aalen, ffi.NULL, nonce, key
+ )
+
+ ensure(res == 0, "Encryption failed.", raising=exc.CryptoError)
+ return ffi.buffer(ciphertext, clen[0])[:]
+
+
+def crypto_aead_chacha20poly1305_decrypt(
+ ciphertext: bytes, aad: Optional[bytes], nonce: bytes, key: bytes
+) -> bytes:
+ """
+ Decrypt the given ``ciphertext`` using the "legacy" construction
+ described in draft-agl-tls-chacha20poly1305.
+
+ :param ciphertext: authenticated ciphertext
+ :type ciphertext: bytes
+ :param aad:
+ :type aad: Optional[bytes]
+ :param nonce:
+ :type nonce: bytes
+ :param key:
+ :type key: bytes
+ :return: message
+ :rtype: bytes
+ """
+ ensure(
+ isinstance(ciphertext, bytes),
+ "Input ciphertext type must be bytes",
+ raising=exc.TypeError,
+ )
+
+ clen = len(ciphertext)
+
+ ensure(
+ clen <= _aead_chacha20poly1305_CRYPTBYTES_MAX,
+ "Ciphertext must be at most {} bytes long".format(
+ _aead_chacha20poly1305_CRYPTBYTES_MAX
+ ),
+ raising=exc.ValueError,
+ )
+
+ ensure(
+ isinstance(aad, bytes) or (aad is None),
+ "Additional data must be bytes or None",
+ raising=exc.TypeError,
+ )
+
+ ensure(
+ isinstance(nonce, bytes)
+ and len(nonce) == crypto_aead_chacha20poly1305_NPUBBYTES,
+ "Nonce must be a {} bytes long bytes sequence".format(
+ crypto_aead_chacha20poly1305_NPUBBYTES
+ ),
+ raising=exc.TypeError,
+ )
+
+ ensure(
+ isinstance(key, bytes)
+ and len(key) == crypto_aead_chacha20poly1305_KEYBYTES,
+ "Key must be a {} bytes long bytes sequence".format(
+ crypto_aead_chacha20poly1305_KEYBYTES
+ ),
+ raising=exc.TypeError,
+ )
+
+ mxout = clen - crypto_aead_chacha20poly1305_ABYTES
+
+ mlen = ffi.new("unsigned long long *")
+ message = ffi.new("unsigned char[]", mxout)
+
+ if aad:
+ _aad = aad
+ aalen = len(aad)
+ else:
+ _aad = ffi.NULL
+ aalen = 0
+
+ res = lib.crypto_aead_chacha20poly1305_decrypt(
+ message, mlen, ffi.NULL, ciphertext, clen, _aad, aalen, nonce, key
+ )
+
+ ensure(res == 0, "Decryption failed.", raising=exc.CryptoError)
+
+ return ffi.buffer(message, mlen[0])[:]
+
+
+def crypto_aead_xchacha20poly1305_ietf_encrypt(
+ message: bytes, aad: Optional[bytes], nonce: bytes, key: bytes
+) -> bytes:
+ """
+ Encrypt the given ``message`` using the long-nonces xchacha20poly1305
+ construction.
+
+ :param message:
+ :type message: bytes
+ :param aad:
+ :type aad: Optional[bytes]
+ :param nonce:
+ :type nonce: bytes
+ :param key:
+ :type key: bytes
+ :return: authenticated ciphertext
+ :rtype: bytes
+ """
+ ensure(
+ isinstance(message, bytes),
+ "Input message type must be bytes",
+ raising=exc.TypeError,
+ )
+
+ mlen = len(message)
+
+ ensure(
+ mlen <= crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX,
+ "Message must be at most {} bytes long".format(
+ crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX
+ ),
+ raising=exc.ValueError,
+ )
+
+ ensure(
+ isinstance(aad, bytes) or (aad is None),
+ "Additional data must be bytes or None",
+ raising=exc.TypeError,
+ )
+
+ ensure(
+ isinstance(nonce, bytes)
+ and len(nonce) == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
+ "Nonce must be a {} bytes long bytes sequence".format(
+ crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
+ ),
+ raising=exc.TypeError,
+ )
+
+ ensure(
+ isinstance(key, bytes)
+ and len(key) == crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
+ "Key must be a {} bytes long bytes sequence".format(
+ crypto_aead_xchacha20poly1305_ietf_KEYBYTES
+ ),
+ raising=exc.TypeError,
+ )
+
+ if aad:
+ _aad = aad
+ aalen = len(aad)
+ else:
+ _aad = ffi.NULL
+ aalen = 0
+
+ mlen = len(message)
+ mxout = mlen + crypto_aead_xchacha20poly1305_ietf_ABYTES
+
+ clen = ffi.new("unsigned long long *")
+
+ ciphertext = ffi.new("unsigned char[]", mxout)
+
+ res = lib.crypto_aead_xchacha20poly1305_ietf_encrypt(
+ ciphertext, clen, message, mlen, _aad, aalen, ffi.NULL, nonce, key
+ )
+
+ ensure(res == 0, "Encryption failed.", raising=exc.CryptoError)
+ return ffi.buffer(ciphertext, clen[0])[:]
+
+
+def crypto_aead_xchacha20poly1305_ietf_decrypt(
+ ciphertext: bytes, aad: Optional[bytes], nonce: bytes, key: bytes
+) -> bytes:
+ """
+ Decrypt the given ``ciphertext`` using the long-nonces xchacha20poly1305
+ construction.
+
+ :param ciphertext: authenticated ciphertext
+ :type ciphertext: bytes
+ :param aad:
+ :type aad: Optional[bytes]
+ :param nonce:
+ :type nonce: bytes
+ :param key:
+ :type key: bytes
+ :return: message
+ :rtype: bytes
+ """
+ ensure(
+ isinstance(ciphertext, bytes),
+ "Input ciphertext type must be bytes",
+ raising=exc.TypeError,
+ )
+
+ clen = len(ciphertext)
+
+ ensure(
+ clen <= _aead_xchacha20poly1305_ietf_CRYPTBYTES_MAX,
+ "Ciphertext must be at most {} bytes long".format(
+ _aead_xchacha20poly1305_ietf_CRYPTBYTES_MAX
+ ),
+ raising=exc.ValueError,
+ )
+
+ ensure(
+ isinstance(aad, bytes) or (aad is None),
+ "Additional data must be bytes or None",
+ raising=exc.TypeError,
+ )
+
+ ensure(
+ isinstance(nonce, bytes)
+ and len(nonce) == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
+ "Nonce must be a {} bytes long bytes sequence".format(
+ crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
+ ),
+ raising=exc.TypeError,
+ )
+
+ ensure(
+ isinstance(key, bytes)
+ and len(key) == crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
+ "Key must be a {} bytes long bytes sequence".format(
+ crypto_aead_xchacha20poly1305_ietf_KEYBYTES
+ ),
+ raising=exc.TypeError,
+ )
+
+ mxout = clen - crypto_aead_xchacha20poly1305_ietf_ABYTES
+ mlen = ffi.new("unsigned long long *")
+ message = ffi.new("unsigned char[]", mxout)
+
+ if aad:
+ _aad = aad
+ aalen = len(aad)
+ else:
+ _aad = ffi.NULL
+ aalen = 0
+
+ res = lib.crypto_aead_xchacha20poly1305_ietf_decrypt(
+ message, mlen, ffi.NULL, ciphertext, clen, _aad, aalen, nonce, key
+ )
+
+ ensure(res == 0, "Decryption failed.", raising=exc.CryptoError)
+
+ return ffi.buffer(message, mlen[0])[:]
diff --git a/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_box.py b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_box.py
new file mode 100644
index 00000000..74f7f0a6
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_box.py
@@ -0,0 +1,324 @@
+# Copyright 2013 Donald Stufft and individual contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from typing import Tuple
+
+from nacl import exceptions as exc
+from nacl._sodium import ffi, lib
+from nacl.exceptions import ensure
+
+
+__all__ = ["crypto_box_keypair", "crypto_box"]
+
+
+crypto_box_SECRETKEYBYTES: int = lib.crypto_box_secretkeybytes()
+crypto_box_PUBLICKEYBYTES: int = lib.crypto_box_publickeybytes()
+crypto_box_SEEDBYTES: int = lib.crypto_box_seedbytes()
+crypto_box_NONCEBYTES: int = lib.crypto_box_noncebytes()
+crypto_box_ZEROBYTES: int = lib.crypto_box_zerobytes()
+crypto_box_BOXZEROBYTES: int = lib.crypto_box_boxzerobytes()
+crypto_box_BEFORENMBYTES: int = lib.crypto_box_beforenmbytes()
+crypto_box_SEALBYTES: int = lib.crypto_box_sealbytes()
+
+
+def crypto_box_keypair() -> Tuple[bytes, bytes]:
+ """
+ Returns a randomly generated public and secret key.
+
+ :rtype: (bytes(public_key), bytes(secret_key))
+ """
+ pk = ffi.new("unsigned char[]", crypto_box_PUBLICKEYBYTES)
+ sk = ffi.new("unsigned char[]", crypto_box_SECRETKEYBYTES)
+
+ rc = lib.crypto_box_keypair(pk, sk)
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+
+ return (
+ ffi.buffer(pk, crypto_box_PUBLICKEYBYTES)[:],
+ ffi.buffer(sk, crypto_box_SECRETKEYBYTES)[:],
+ )
+
+
+def crypto_box_seed_keypair(seed: bytes) -> Tuple[bytes, bytes]:
+ """
+ Returns a (public, secret) keypair deterministically generated
+ from an input ``seed``.
+
+ .. warning:: The seed **must** be high-entropy; therefore,
+ its generator **must** be a cryptographic quality
+ random function like, for example, :func:`~nacl.utils.random`.
+
+ .. warning:: The seed **must** be protected and remain secret.
+ Anyone who knows the seed is really in possession of
+ the corresponding PrivateKey.
+
+
+ :param seed: bytes
+ :rtype: (bytes(public_key), bytes(secret_key))
+ """
+ ensure(isinstance(seed, bytes), "seed must be bytes", raising=TypeError)
+
+ if len(seed) != crypto_box_SEEDBYTES:
+ raise exc.ValueError("Invalid seed")
+
+ pk = ffi.new("unsigned char[]", crypto_box_PUBLICKEYBYTES)
+ sk = ffi.new("unsigned char[]", crypto_box_SECRETKEYBYTES)
+
+ rc = lib.crypto_box_seed_keypair(pk, sk, seed)
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+
+ return (
+ ffi.buffer(pk, crypto_box_PUBLICKEYBYTES)[:],
+ ffi.buffer(sk, crypto_box_SECRETKEYBYTES)[:],
+ )
+
+
+def crypto_box(message: bytes, nonce: bytes, pk: bytes, sk: bytes) -> bytes:
+ """
+ Encrypts and returns a message ``message`` using the secret key ``sk``,
+ public key ``pk``, and the nonce ``nonce``.
+
+ :param message: bytes
+ :param nonce: bytes
+ :param pk: bytes
+ :param sk: bytes
+ :rtype: bytes
+ """
+ if len(nonce) != crypto_box_NONCEBYTES:
+ raise exc.ValueError("Invalid nonce size")
+
+ if len(pk) != crypto_box_PUBLICKEYBYTES:
+ raise exc.ValueError("Invalid public key")
+
+ if len(sk) != crypto_box_SECRETKEYBYTES:
+ raise exc.ValueError("Invalid secret key")
+
+ padded = (b"\x00" * crypto_box_ZEROBYTES) + message
+ ciphertext = ffi.new("unsigned char[]", len(padded))
+
+ rc = lib.crypto_box(ciphertext, padded, len(padded), nonce, pk, sk)
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+
+ return ffi.buffer(ciphertext, len(padded))[crypto_box_BOXZEROBYTES:]
+
+
+def crypto_box_open(
+ ciphertext: bytes, nonce: bytes, pk: bytes, sk: bytes
+) -> bytes:
+ """
+ Decrypts and returns an encrypted message ``ciphertext``, using the secret
+ key ``sk``, public key ``pk``, and the nonce ``nonce``.
+
+ :param ciphertext: bytes
+ :param nonce: bytes
+ :param pk: bytes
+ :param sk: bytes
+ :rtype: bytes
+ """
+ if len(nonce) != crypto_box_NONCEBYTES:
+ raise exc.ValueError("Invalid nonce size")
+
+ if len(pk) != crypto_box_PUBLICKEYBYTES:
+ raise exc.ValueError("Invalid public key")
+
+ if len(sk) != crypto_box_SECRETKEYBYTES:
+ raise exc.ValueError("Invalid secret key")
+
+ padded = (b"\x00" * crypto_box_BOXZEROBYTES) + ciphertext
+ plaintext = ffi.new("unsigned char[]", len(padded))
+
+ res = lib.crypto_box_open(plaintext, padded, len(padded), nonce, pk, sk)
+ ensure(
+ res == 0,
+ "An error occurred trying to decrypt the message",
+ raising=exc.CryptoError,
+ )
+
+ return ffi.buffer(plaintext, len(padded))[crypto_box_ZEROBYTES:]
+
+
+def crypto_box_beforenm(pk: bytes, sk: bytes) -> bytes:
+ """
+ Computes and returns the shared key for the public key ``pk`` and the
+ secret key ``sk``. This can be used to speed up operations where the same
+ set of keys is going to be used multiple times.
+
+ :param pk: bytes
+ :param sk: bytes
+ :rtype: bytes
+ """
+ if len(pk) != crypto_box_PUBLICKEYBYTES:
+ raise exc.ValueError("Invalid public key")
+
+ if len(sk) != crypto_box_SECRETKEYBYTES:
+ raise exc.ValueError("Invalid secret key")
+
+ k = ffi.new("unsigned char[]", crypto_box_BEFORENMBYTES)
+
+ rc = lib.crypto_box_beforenm(k, pk, sk)
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+
+ return ffi.buffer(k, crypto_box_BEFORENMBYTES)[:]
+
+
+def crypto_box_afternm(message: bytes, nonce: bytes, k: bytes) -> bytes:
+ """
+ Encrypts and returns the message ``message`` using the shared key ``k`` and
+ the nonce ``nonce``.
+
+ :param message: bytes
+ :param nonce: bytes
+ :param k: bytes
+ :rtype: bytes
+ """
+ if len(nonce) != crypto_box_NONCEBYTES:
+ raise exc.ValueError("Invalid nonce")
+
+ if len(k) != crypto_box_BEFORENMBYTES:
+ raise exc.ValueError("Invalid shared key")
+
+ padded = b"\x00" * crypto_box_ZEROBYTES + message
+ ciphertext = ffi.new("unsigned char[]", len(padded))
+
+ rc = lib.crypto_box_afternm(ciphertext, padded, len(padded), nonce, k)
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+
+ return ffi.buffer(ciphertext, len(padded))[crypto_box_BOXZEROBYTES:]
+
+
+def crypto_box_open_afternm(
+ ciphertext: bytes, nonce: bytes, k: bytes
+) -> bytes:
+ """
+ Decrypts and returns the encrypted message ``ciphertext``, using the shared
+ key ``k`` and the nonce ``nonce``.
+
+ :param ciphertext: bytes
+ :param nonce: bytes
+ :param k: bytes
+ :rtype: bytes
+ """
+ if len(nonce) != crypto_box_NONCEBYTES:
+ raise exc.ValueError("Invalid nonce")
+
+ if len(k) != crypto_box_BEFORENMBYTES:
+ raise exc.ValueError("Invalid shared key")
+
+ padded = (b"\x00" * crypto_box_BOXZEROBYTES) + ciphertext
+ plaintext = ffi.new("unsigned char[]", len(padded))
+
+ res = lib.crypto_box_open_afternm(plaintext, padded, len(padded), nonce, k)
+ ensure(
+ res == 0,
+ "An error occurred trying to decrypt the message",
+ raising=exc.CryptoError,
+ )
+
+ return ffi.buffer(plaintext, len(padded))[crypto_box_ZEROBYTES:]
+
+
+def crypto_box_seal(message: bytes, pk: bytes) -> bytes:
+ """
+ Encrypts and returns a message ``message`` using an ephemeral secret key
+ and the public key ``pk``.
+ The ephemeral public key, which is embedded in the sealed box, is also
+ used, in combination with ``pk``, to derive the nonce needed for the
+ underlying box construct.
+
+ :param message: bytes
+ :param pk: bytes
+ :rtype: bytes
+
+ .. versionadded:: 1.2
+ """
+ ensure(
+ isinstance(message, bytes),
+ "input message must be bytes",
+ raising=TypeError,
+ )
+
+ ensure(
+ isinstance(pk, bytes), "public key must be bytes", raising=TypeError
+ )
+
+ if len(pk) != crypto_box_PUBLICKEYBYTES:
+ raise exc.ValueError("Invalid public key")
+
+ _mlen = len(message)
+ _clen = crypto_box_SEALBYTES + _mlen
+
+ ciphertext = ffi.new("unsigned char[]", _clen)
+
+ rc = lib.crypto_box_seal(ciphertext, message, _mlen, pk)
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+
+ return ffi.buffer(ciphertext, _clen)[:]
+
+
+def crypto_box_seal_open(ciphertext: bytes, pk: bytes, sk: bytes) -> bytes:
+ """
+ Decrypts and returns an encrypted message ``ciphertext``, using the
+ recipent's secret key ``sk`` and the sender's ephemeral public key
+ embedded in the sealed box. The box contruct nonce is derived from
+ the recipient's public key ``pk`` and the sender's public key.
+
+ :param ciphertext: bytes
+ :param pk: bytes
+ :param sk: bytes
+ :rtype: bytes
+
+ .. versionadded:: 1.2
+ """
+ ensure(
+ isinstance(ciphertext, bytes),
+ "input ciphertext must be bytes",
+ raising=TypeError,
+ )
+
+ ensure(
+ isinstance(pk, bytes), "public key must be bytes", raising=TypeError
+ )
+
+ ensure(
+ isinstance(sk, bytes), "secret key must be bytes", raising=TypeError
+ )
+
+ if len(pk) != crypto_box_PUBLICKEYBYTES:
+ raise exc.ValueError("Invalid public key")
+
+ if len(sk) != crypto_box_SECRETKEYBYTES:
+ raise exc.ValueError("Invalid secret key")
+
+ _clen = len(ciphertext)
+
+ ensure(
+ _clen >= crypto_box_SEALBYTES,
+ ("Input cyphertext must be at least {} long").format(
+ crypto_box_SEALBYTES
+ ),
+ raising=exc.TypeError,
+ )
+
+ _mlen = _clen - crypto_box_SEALBYTES
+
+ # zero-length malloc results are implementation.dependent
+ plaintext = ffi.new("unsigned char[]", max(1, _mlen))
+
+ res = lib.crypto_box_seal_open(plaintext, ciphertext, _clen, pk, sk)
+ ensure(
+ res == 0,
+ "An error occurred trying to decrypt the message",
+ raising=exc.CryptoError,
+ )
+
+ return ffi.buffer(plaintext, _mlen)[:]
diff --git a/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_core.py b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_core.py
new file mode 100644
index 00000000..d29da9b3
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_core.py
@@ -0,0 +1,412 @@
+# Copyright 2018 Donald Stufft and individual contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+from nacl import exceptions as exc
+from nacl._sodium import ffi, lib
+from nacl.exceptions import ensure
+
+
+has_crypto_core_ed25519 = bool(lib.PYNACL_HAS_CRYPTO_CORE_ED25519)
+
+crypto_core_ed25519_BYTES = 0
+crypto_core_ed25519_SCALARBYTES = 0
+crypto_core_ed25519_NONREDUCEDSCALARBYTES = 0
+
+if has_crypto_core_ed25519:
+ crypto_core_ed25519_BYTES = lib.crypto_core_ed25519_bytes()
+ crypto_core_ed25519_SCALARBYTES = lib.crypto_core_ed25519_scalarbytes()
+ crypto_core_ed25519_NONREDUCEDSCALARBYTES = (
+ lib.crypto_core_ed25519_nonreducedscalarbytes()
+ )
+
+
+def crypto_core_ed25519_is_valid_point(p: bytes) -> bool:
+ """
+ Check if ``p`` represents a point on the edwards25519 curve, in canonical
+ form, on the main subgroup, and that the point doesn't have a small order.
+
+ :param p: a :py:data:`.crypto_core_ed25519_BYTES` long bytes sequence
+ representing a point on the edwards25519 curve
+ :type p: bytes
+ :return: point validity
+ :rtype: bool
+ :raises nacl.exceptions.UnavailableError: If called when using a
+ minimal build of libsodium.
+ """
+ ensure(
+ has_crypto_core_ed25519,
+ "Not available in minimal build",
+ raising=exc.UnavailableError,
+ )
+
+ ensure(
+ isinstance(p, bytes) and len(p) == crypto_core_ed25519_BYTES,
+ "Point must be a crypto_core_ed25519_BYTES long bytes sequence",
+ raising=exc.TypeError,
+ )
+
+ rc = lib.crypto_core_ed25519_is_valid_point(p)
+ return rc == 1
+
+
+def crypto_core_ed25519_add(p: bytes, q: bytes) -> bytes:
+ """
+ Add two points on the edwards25519 curve.
+
+ :param p: a :py:data:`.crypto_core_ed25519_BYTES` long bytes sequence
+ representing a point on the edwards25519 curve
+ :type p: bytes
+ :param q: a :py:data:`.crypto_core_ed25519_BYTES` long bytes sequence
+ representing a point on the edwards25519 curve
+ :type q: bytes
+ :return: a point on the edwards25519 curve represented as
+ a :py:data:`.crypto_core_ed25519_BYTES` long bytes sequence
+ :rtype: bytes
+ :raises nacl.exceptions.UnavailableError: If called when using a
+ minimal build of libsodium.
+ """
+ ensure(
+ has_crypto_core_ed25519,
+ "Not available in minimal build",
+ raising=exc.UnavailableError,
+ )
+
+ ensure(
+ isinstance(p, bytes)
+ and isinstance(q, bytes)
+ and len(p) == crypto_core_ed25519_BYTES
+ and len(q) == crypto_core_ed25519_BYTES,
+ "Each point must be a {} long bytes sequence".format(
+ "crypto_core_ed25519_BYTES"
+ ),
+ raising=exc.TypeError,
+ )
+
+ r = ffi.new("unsigned char[]", crypto_core_ed25519_BYTES)
+
+ rc = lib.crypto_core_ed25519_add(r, p, q)
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+
+ return ffi.buffer(r, crypto_core_ed25519_BYTES)[:]
+
+
+def crypto_core_ed25519_sub(p: bytes, q: bytes) -> bytes:
+ """
+ Subtract a point from another on the edwards25519 curve.
+
+ :param p: a :py:data:`.crypto_core_ed25519_BYTES` long bytes sequence
+ representing a point on the edwards25519 curve
+ :type p: bytes
+ :param q: a :py:data:`.crypto_core_ed25519_BYTES` long bytes sequence
+ representing a point on the edwards25519 curve
+ :type q: bytes
+ :return: a point on the edwards25519 curve represented as
+ a :py:data:`.crypto_core_ed25519_BYTES` long bytes sequence
+ :rtype: bytes
+ :raises nacl.exceptions.UnavailableError: If called when using a
+ minimal build of libsodium.
+ """
+ ensure(
+ has_crypto_core_ed25519,
+ "Not available in minimal build",
+ raising=exc.UnavailableError,
+ )
+
+ ensure(
+ isinstance(p, bytes)
+ and isinstance(q, bytes)
+ and len(p) == crypto_core_ed25519_BYTES
+ and len(q) == crypto_core_ed25519_BYTES,
+ "Each point must be a {} long bytes sequence".format(
+ "crypto_core_ed25519_BYTES"
+ ),
+ raising=exc.TypeError,
+ )
+
+ r = ffi.new("unsigned char[]", crypto_core_ed25519_BYTES)
+
+ rc = lib.crypto_core_ed25519_sub(r, p, q)
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+
+ return ffi.buffer(r, crypto_core_ed25519_BYTES)[:]
+
+
+def crypto_core_ed25519_scalar_invert(s: bytes) -> bytes:
+ """
+ Return the multiplicative inverse of integer ``s`` modulo ``L``,
+ i.e an integer ``i`` such that ``s * i = 1 (mod L)``, where ``L``
+ is the order of the main subgroup.
+
+ Raises a ``exc.RuntimeError`` if ``s`` is the integer zero.
+
+ :param s: a :py:data:`.crypto_core_ed25519_SCALARBYTES`
+ long bytes sequence representing an integer
+ :type s: bytes
+ :return: an integer represented as a
+ :py:data:`.crypto_core_ed25519_SCALARBYTES` long bytes sequence
+ :rtype: bytes
+ :raises nacl.exceptions.UnavailableError: If called when using a
+ minimal build of libsodium.
+ """
+ ensure(
+ has_crypto_core_ed25519,
+ "Not available in minimal build",
+ raising=exc.UnavailableError,
+ )
+
+ ensure(
+ isinstance(s, bytes) and len(s) == crypto_core_ed25519_SCALARBYTES,
+ "Integer s must be a {} long bytes sequence".format(
+ "crypto_core_ed25519_SCALARBYTES"
+ ),
+ raising=exc.TypeError,
+ )
+
+ r = ffi.new("unsigned char[]", crypto_core_ed25519_SCALARBYTES)
+
+ rc = lib.crypto_core_ed25519_scalar_invert(r, s)
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+
+ return ffi.buffer(r, crypto_core_ed25519_SCALARBYTES)[:]
+
+
+def crypto_core_ed25519_scalar_negate(s: bytes) -> bytes:
+ """
+ Return the integer ``n`` such that ``s + n = 0 (mod L)``, where ``L``
+ is the order of the main subgroup.
+
+ :param s: a :py:data:`.crypto_core_ed25519_SCALARBYTES`
+ long bytes sequence representing an integer
+ :type s: bytes
+ :return: an integer represented as a
+ :py:data:`.crypto_core_ed25519_SCALARBYTES` long bytes sequence
+ :rtype: bytes
+ :raises nacl.exceptions.UnavailableError: If called when using a
+ minimal build of libsodium.
+ """
+ ensure(
+ has_crypto_core_ed25519,
+ "Not available in minimal build",
+ raising=exc.UnavailableError,
+ )
+
+ ensure(
+ isinstance(s, bytes) and len(s) == crypto_core_ed25519_SCALARBYTES,
+ "Integer s must be a {} long bytes sequence".format(
+ "crypto_core_ed25519_SCALARBYTES"
+ ),
+ raising=exc.TypeError,
+ )
+
+ r = ffi.new("unsigned char[]", crypto_core_ed25519_SCALARBYTES)
+
+ lib.crypto_core_ed25519_scalar_negate(r, s)
+
+ return ffi.buffer(r, crypto_core_ed25519_SCALARBYTES)[:]
+
+
+def crypto_core_ed25519_scalar_complement(s: bytes) -> bytes:
+ """
+ Return the complement of integer ``s`` modulo ``L``, i.e. an integer
+ ``c`` such that ``s + c = 1 (mod L)``, where ``L`` is the order of
+ the main subgroup.
+
+ :param s: a :py:data:`.crypto_core_ed25519_SCALARBYTES`
+ long bytes sequence representing an integer
+ :type s: bytes
+ :return: an integer represented as a
+ :py:data:`.crypto_core_ed25519_SCALARBYTES` long bytes sequence
+ :rtype: bytes
+ :raises nacl.exceptions.UnavailableError: If called when using a
+ minimal build of libsodium.
+ """
+ ensure(
+ has_crypto_core_ed25519,
+ "Not available in minimal build",
+ raising=exc.UnavailableError,
+ )
+
+ ensure(
+ isinstance(s, bytes) and len(s) == crypto_core_ed25519_SCALARBYTES,
+ "Integer s must be a {} long bytes sequence".format(
+ "crypto_core_ed25519_SCALARBYTES"
+ ),
+ raising=exc.TypeError,
+ )
+
+ r = ffi.new("unsigned char[]", crypto_core_ed25519_SCALARBYTES)
+
+ lib.crypto_core_ed25519_scalar_complement(r, s)
+
+ return ffi.buffer(r, crypto_core_ed25519_SCALARBYTES)[:]
+
+
+def crypto_core_ed25519_scalar_add(p: bytes, q: bytes) -> bytes:
+ """
+ Add integers ``p`` and ``q`` modulo ``L``, where ``L`` is the order of
+ the main subgroup.
+
+ :param p: a :py:data:`.crypto_core_ed25519_SCALARBYTES`
+ long bytes sequence representing an integer
+ :type p: bytes
+ :param q: a :py:data:`.crypto_core_ed25519_SCALARBYTES`
+ long bytes sequence representing an integer
+ :type q: bytes
+ :return: an integer represented as a
+ :py:data:`.crypto_core_ed25519_SCALARBYTES` long bytes sequence
+ :rtype: bytes
+ :raises nacl.exceptions.UnavailableError: If called when using a
+ minimal build of libsodium.
+ """
+ ensure(
+ has_crypto_core_ed25519,
+ "Not available in minimal build",
+ raising=exc.UnavailableError,
+ )
+
+ ensure(
+ isinstance(p, bytes)
+ and isinstance(q, bytes)
+ and len(p) == crypto_core_ed25519_SCALARBYTES
+ and len(q) == crypto_core_ed25519_SCALARBYTES,
+ "Each integer must be a {} long bytes sequence".format(
+ "crypto_core_ed25519_SCALARBYTES"
+ ),
+ raising=exc.TypeError,
+ )
+
+ r = ffi.new("unsigned char[]", crypto_core_ed25519_SCALARBYTES)
+
+ lib.crypto_core_ed25519_scalar_add(r, p, q)
+
+ return ffi.buffer(r, crypto_core_ed25519_SCALARBYTES)[:]
+
+
+def crypto_core_ed25519_scalar_sub(p: bytes, q: bytes) -> bytes:
+ """
+ Subtract integers ``p`` and ``q`` modulo ``L``, where ``L`` is the
+ order of the main subgroup.
+
+ :param p: a :py:data:`.crypto_core_ed25519_SCALARBYTES`
+ long bytes sequence representing an integer
+ :type p: bytes
+ :param q: a :py:data:`.crypto_core_ed25519_SCALARBYTES`
+ long bytes sequence representing an integer
+ :type q: bytes
+ :return: an integer represented as a
+ :py:data:`.crypto_core_ed25519_SCALARBYTES` long bytes sequence
+ :rtype: bytes
+ :raises nacl.exceptions.UnavailableError: If called when using a
+ minimal build of libsodium.
+ """
+ ensure(
+ has_crypto_core_ed25519,
+ "Not available in minimal build",
+ raising=exc.UnavailableError,
+ )
+
+ ensure(
+ isinstance(p, bytes)
+ and isinstance(q, bytes)
+ and len(p) == crypto_core_ed25519_SCALARBYTES
+ and len(q) == crypto_core_ed25519_SCALARBYTES,
+ "Each integer must be a {} long bytes sequence".format(
+ "crypto_core_ed25519_SCALARBYTES"
+ ),
+ raising=exc.TypeError,
+ )
+
+ r = ffi.new("unsigned char[]", crypto_core_ed25519_SCALARBYTES)
+
+ lib.crypto_core_ed25519_scalar_sub(r, p, q)
+
+ return ffi.buffer(r, crypto_core_ed25519_SCALARBYTES)[:]
+
+
+def crypto_core_ed25519_scalar_mul(p: bytes, q: bytes) -> bytes:
+ """
+ Multiply integers ``p`` and ``q`` modulo ``L``, where ``L`` is the
+ order of the main subgroup.
+
+ :param p: a :py:data:`.crypto_core_ed25519_SCALARBYTES`
+ long bytes sequence representing an integer
+ :type p: bytes
+ :param q: a :py:data:`.crypto_core_ed25519_SCALARBYTES`
+ long bytes sequence representing an integer
+ :type q: bytes
+ :return: an integer represented as a
+ :py:data:`.crypto_core_ed25519_SCALARBYTES` long bytes sequence
+ :rtype: bytes
+ :raises nacl.exceptions.UnavailableError: If called when using a
+ minimal build of libsodium.
+ """
+ ensure(
+ has_crypto_core_ed25519,
+ "Not available in minimal build",
+ raising=exc.UnavailableError,
+ )
+
+ ensure(
+ isinstance(p, bytes)
+ and isinstance(q, bytes)
+ and len(p) == crypto_core_ed25519_SCALARBYTES
+ and len(q) == crypto_core_ed25519_SCALARBYTES,
+ "Each integer must be a {} long bytes sequence".format(
+ "crypto_core_ed25519_SCALARBYTES"
+ ),
+ raising=exc.TypeError,
+ )
+
+ r = ffi.new("unsigned char[]", crypto_core_ed25519_SCALARBYTES)
+
+ lib.crypto_core_ed25519_scalar_mul(r, p, q)
+
+ return ffi.buffer(r, crypto_core_ed25519_SCALARBYTES)[:]
+
+
+def crypto_core_ed25519_scalar_reduce(s: bytes) -> bytes:
+ """
+ Reduce integer ``s`` to ``s`` modulo ``L``, where ``L`` is the order
+ of the main subgroup.
+
+ :param s: a :py:data:`.crypto_core_ed25519_NONREDUCEDSCALARBYTES`
+ long bytes sequence representing an integer
+ :type s: bytes
+ :return: an integer represented as a
+ :py:data:`.crypto_core_ed25519_SCALARBYTES` long bytes sequence
+ :rtype: bytes
+ :raises nacl.exceptions.UnavailableError: If called when using a
+ minimal build of libsodium.
+ """
+ ensure(
+ has_crypto_core_ed25519,
+ "Not available in minimal build",
+ raising=exc.UnavailableError,
+ )
+
+ ensure(
+ isinstance(s, bytes)
+ and len(s) == crypto_core_ed25519_NONREDUCEDSCALARBYTES,
+ "Integer s must be a {} long bytes sequence".format(
+ "crypto_core_ed25519_NONREDUCEDSCALARBYTES"
+ ),
+ raising=exc.TypeError,
+ )
+
+ r = ffi.new("unsigned char[]", crypto_core_ed25519_SCALARBYTES)
+
+ lib.crypto_core_ed25519_scalar_reduce(r, s)
+
+ return ffi.buffer(r, crypto_core_ed25519_SCALARBYTES)[:]
diff --git a/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_generichash.py b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_generichash.py
new file mode 100644
index 00000000..6ab385a5
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_generichash.py
@@ -0,0 +1,281 @@
+# Copyright 2013-2019 Donald Stufft and individual contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from typing import NoReturn, TypeVar
+
+from nacl import exceptions as exc
+from nacl._sodium import ffi, lib
+from nacl.exceptions import ensure
+
+
+crypto_generichash_BYTES: int = lib.crypto_generichash_blake2b_bytes()
+crypto_generichash_BYTES_MIN: int = lib.crypto_generichash_blake2b_bytes_min()
+crypto_generichash_BYTES_MAX: int = lib.crypto_generichash_blake2b_bytes_max()
+crypto_generichash_KEYBYTES: int = lib.crypto_generichash_blake2b_keybytes()
+crypto_generichash_KEYBYTES_MIN: int = (
+ lib.crypto_generichash_blake2b_keybytes_min()
+)
+crypto_generichash_KEYBYTES_MAX: int = (
+ lib.crypto_generichash_blake2b_keybytes_max()
+)
+crypto_generichash_SALTBYTES: int = lib.crypto_generichash_blake2b_saltbytes()
+crypto_generichash_PERSONALBYTES: int = (
+ lib.crypto_generichash_blake2b_personalbytes()
+)
+crypto_generichash_STATEBYTES: int = lib.crypto_generichash_statebytes()
+
+_OVERLONG = "{0} length greater than {1} bytes"
+_TOOBIG = "{0} greater than {1}"
+
+
+def _checkparams(
+ digest_size: int, key: bytes, salt: bytes, person: bytes
+) -> None:
+ """Check hash parameters"""
+ ensure(
+ isinstance(key, bytes),
+ "Key must be a bytes sequence",
+ raising=exc.TypeError,
+ )
+
+ ensure(
+ isinstance(salt, bytes),
+ "Salt must be a bytes sequence",
+ raising=exc.TypeError,
+ )
+
+ ensure(
+ isinstance(person, bytes),
+ "Person must be a bytes sequence",
+ raising=exc.TypeError,
+ )
+
+ ensure(
+ isinstance(digest_size, int),
+ "Digest size must be an integer number",
+ raising=exc.TypeError,
+ )
+
+ ensure(
+ digest_size <= crypto_generichash_BYTES_MAX,
+ _TOOBIG.format("Digest_size", crypto_generichash_BYTES_MAX),
+ raising=exc.ValueError,
+ )
+
+ ensure(
+ len(key) <= crypto_generichash_KEYBYTES_MAX,
+ _OVERLONG.format("Key", crypto_generichash_KEYBYTES_MAX),
+ raising=exc.ValueError,
+ )
+
+ ensure(
+ len(salt) <= crypto_generichash_SALTBYTES,
+ _OVERLONG.format("Salt", crypto_generichash_SALTBYTES),
+ raising=exc.ValueError,
+ )
+
+ ensure(
+ len(person) <= crypto_generichash_PERSONALBYTES,
+ _OVERLONG.format("Person", crypto_generichash_PERSONALBYTES),
+ raising=exc.ValueError,
+ )
+
+
+def generichash_blake2b_salt_personal(
+ data: bytes,
+ digest_size: int = crypto_generichash_BYTES,
+ key: bytes = b"",
+ salt: bytes = b"",
+ person: bytes = b"",
+) -> bytes:
+ """One shot hash interface
+
+ :param data: the input data to the hash function
+ :type data: bytes
+ :param digest_size: must be at most
+ :py:data:`.crypto_generichash_BYTES_MAX`;
+ the default digest size is
+ :py:data:`.crypto_generichash_BYTES`
+ :type digest_size: int
+ :param key: must be at most
+ :py:data:`.crypto_generichash_KEYBYTES_MAX` long
+ :type key: bytes
+ :param salt: must be at most
+ :py:data:`.crypto_generichash_SALTBYTES` long;
+ will be zero-padded if needed
+ :type salt: bytes
+ :param person: must be at most
+ :py:data:`.crypto_generichash_PERSONALBYTES` long:
+ will be zero-padded if needed
+ :type person: bytes
+ :return: digest_size long digest
+ :rtype: bytes
+ """
+
+ _checkparams(digest_size, key, salt, person)
+
+ ensure(
+ isinstance(data, bytes),
+ "Input data must be a bytes sequence",
+ raising=exc.TypeError,
+ )
+
+ digest = ffi.new("unsigned char[]", digest_size)
+
+ # both _salt and _personal must be zero-padded to the correct length
+ _salt = ffi.new("unsigned char []", crypto_generichash_SALTBYTES)
+ _person = ffi.new("unsigned char []", crypto_generichash_PERSONALBYTES)
+
+ ffi.memmove(_salt, salt, len(salt))
+ ffi.memmove(_person, person, len(person))
+
+ rc = lib.crypto_generichash_blake2b_salt_personal(
+ digest, digest_size, data, len(data), key, len(key), _salt, _person
+ )
+ ensure(rc == 0, "Unexpected failure", raising=exc.RuntimeError)
+
+ return ffi.buffer(digest, digest_size)[:]
+
+
+_Blake2State = TypeVar("_Blake2State", bound="Blake2State")
+
+
+class Blake2State:
+ """
+ Python-level wrapper for the crypto_generichash_blake2b state buffer
+ """
+
+ __slots__ = ["_statebuf", "digest_size"]
+
+ def __init__(self, digest_size: int):
+ self._statebuf = ffi.new(
+ "unsigned char[]", crypto_generichash_STATEBYTES
+ )
+ self.digest_size = digest_size
+
+ def __reduce__(self) -> NoReturn:
+ """
+ Raise the same exception as hashlib's blake implementation
+ on copy.copy()
+ """
+ raise TypeError(
+ "can't pickle {} objects".format(self.__class__.__name__)
+ )
+
+ def copy(self: _Blake2State) -> _Blake2State:
+ _st = self.__class__(self.digest_size)
+ ffi.memmove(
+ _st._statebuf, self._statebuf, crypto_generichash_STATEBYTES
+ )
+ return _st
+
+
+def generichash_blake2b_init(
+ key: bytes = b"",
+ salt: bytes = b"",
+ person: bytes = b"",
+ digest_size: int = crypto_generichash_BYTES,
+) -> Blake2State:
+ """
+ Create a new initialized blake2b hash state
+
+ :param key: must be at most
+ :py:data:`.crypto_generichash_KEYBYTES_MAX` long
+ :type key: bytes
+ :param salt: must be at most
+ :py:data:`.crypto_generichash_SALTBYTES` long;
+ will be zero-padded if needed
+ :type salt: bytes
+ :param person: must be at most
+ :py:data:`.crypto_generichash_PERSONALBYTES` long:
+ will be zero-padded if needed
+ :type person: bytes
+ :param digest_size: must be at most
+ :py:data:`.crypto_generichash_BYTES_MAX`;
+ the default digest size is
+ :py:data:`.crypto_generichash_BYTES`
+ :type digest_size: int
+ :return: a initialized :py:class:`.Blake2State`
+ :rtype: object
+ """
+
+ _checkparams(digest_size, key, salt, person)
+
+ state = Blake2State(digest_size)
+
+ # both _salt and _personal must be zero-padded to the correct length
+ _salt = ffi.new("unsigned char []", crypto_generichash_SALTBYTES)
+ _person = ffi.new("unsigned char []", crypto_generichash_PERSONALBYTES)
+
+ ffi.memmove(_salt, salt, len(salt))
+ ffi.memmove(_person, person, len(person))
+
+ rc = lib.crypto_generichash_blake2b_init_salt_personal(
+ state._statebuf, key, len(key), digest_size, _salt, _person
+ )
+ ensure(rc == 0, "Unexpected failure", raising=exc.RuntimeError)
+
+ return state
+
+
+def generichash_blake2b_update(state: Blake2State, data: bytes) -> None:
+ """Update the blake2b hash state
+
+ :param state: a initialized Blake2bState object as returned from
+ :py:func:`.crypto_generichash_blake2b_init`
+ :type state: :py:class:`.Blake2State`
+ :param data:
+ :type data: bytes
+ """
+
+ ensure(
+ isinstance(state, Blake2State),
+ "State must be a Blake2State object",
+ raising=exc.TypeError,
+ )
+
+ ensure(
+ isinstance(data, bytes),
+ "Input data must be a bytes sequence",
+ raising=exc.TypeError,
+ )
+
+ rc = lib.crypto_generichash_blake2b_update(
+ state._statebuf, data, len(data)
+ )
+ ensure(rc == 0, "Unexpected failure", raising=exc.RuntimeError)
+
+
+def generichash_blake2b_final(state: Blake2State) -> bytes:
+ """Finalize the blake2b hash state and return the digest.
+
+ :param state: a initialized Blake2bState object as returned from
+ :py:func:`.crypto_generichash_blake2b_init`
+ :type state: :py:class:`.Blake2State`
+ :return: the blake2 digest of the passed-in data stream
+ :rtype: bytes
+ """
+
+ ensure(
+ isinstance(state, Blake2State),
+ "State must be a Blake2State object",
+ raising=exc.TypeError,
+ )
+
+ _digest = ffi.new("unsigned char[]", crypto_generichash_BYTES_MAX)
+ rc = lib.crypto_generichash_blake2b_final(
+ state._statebuf, _digest, state.digest_size
+ )
+
+ ensure(rc == 0, "Unexpected failure", raising=exc.RuntimeError)
+ return ffi.buffer(_digest, state.digest_size)[:]
diff --git a/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_hash.py b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_hash.py
new file mode 100644
index 00000000..2bab3991
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_hash.py
@@ -0,0 +1,63 @@
+# Copyright 2013 Donald Stufft and individual contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+from nacl import exceptions as exc
+from nacl._sodium import ffi, lib
+from nacl.exceptions import ensure
+
+
+# crypto_hash_BYTES = lib.crypto_hash_bytes()
+crypto_hash_BYTES: int = lib.crypto_hash_sha512_bytes()
+crypto_hash_sha256_BYTES: int = lib.crypto_hash_sha256_bytes()
+crypto_hash_sha512_BYTES: int = lib.crypto_hash_sha512_bytes()
+
+
+def crypto_hash(message: bytes) -> bytes:
+ """
+ Hashes and returns the message ``message``.
+
+ :param message: bytes
+ :rtype: bytes
+ """
+ digest = ffi.new("unsigned char[]", crypto_hash_BYTES)
+ rc = lib.crypto_hash(digest, message, len(message))
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+ return ffi.buffer(digest, crypto_hash_BYTES)[:]
+
+
+def crypto_hash_sha256(message: bytes) -> bytes:
+ """
+ Hashes and returns the message ``message``.
+
+ :param message: bytes
+ :rtype: bytes
+ """
+ digest = ffi.new("unsigned char[]", crypto_hash_sha256_BYTES)
+ rc = lib.crypto_hash_sha256(digest, message, len(message))
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+ return ffi.buffer(digest, crypto_hash_sha256_BYTES)[:]
+
+
+def crypto_hash_sha512(message: bytes) -> bytes:
+ """
+ Hashes and returns the message ``message``.
+
+ :param message: bytes
+ :rtype: bytes
+ """
+ digest = ffi.new("unsigned char[]", crypto_hash_sha512_BYTES)
+ rc = lib.crypto_hash_sha512(digest, message, len(message))
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+ return ffi.buffer(digest, crypto_hash_sha512_BYTES)[:]
diff --git a/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_kx.py b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_kx.py
new file mode 100644
index 00000000..172a19f8
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_kx.py
@@ -0,0 +1,200 @@
+# Copyright 2018 Donald Stufft and individual contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from typing import Tuple
+
+from nacl import exceptions as exc
+from nacl._sodium import ffi, lib
+from nacl.exceptions import ensure
+
+__all__ = [
+ "crypto_kx_keypair",
+ "crypto_kx_client_session_keys",
+ "crypto_kx_server_session_keys",
+ "crypto_kx_PUBLIC_KEY_BYTES",
+ "crypto_kx_SECRET_KEY_BYTES",
+ "crypto_kx_SEED_BYTES",
+ "crypto_kx_SESSION_KEY_BYTES",
+]
+
+"""
+Implementations of client, server key exchange
+"""
+crypto_kx_PUBLIC_KEY_BYTES: int = lib.crypto_kx_publickeybytes()
+crypto_kx_SECRET_KEY_BYTES: int = lib.crypto_kx_secretkeybytes()
+crypto_kx_SEED_BYTES: int = lib.crypto_kx_seedbytes()
+crypto_kx_SESSION_KEY_BYTES: int = lib.crypto_kx_sessionkeybytes()
+
+
+def crypto_kx_keypair() -> Tuple[bytes, bytes]:
+ """
+ Generate a keypair.
+ This is a duplicate crypto_box_keypair, but
+ is included for api consistency.
+ :return: (public_key, secret_key)
+ :rtype: (bytes, bytes)
+ """
+ public_key = ffi.new("unsigned char[]", crypto_kx_PUBLIC_KEY_BYTES)
+ secret_key = ffi.new("unsigned char[]", crypto_kx_SECRET_KEY_BYTES)
+ res = lib.crypto_kx_keypair(public_key, secret_key)
+ ensure(res == 0, "Key generation failed.", raising=exc.CryptoError)
+
+ return (
+ ffi.buffer(public_key, crypto_kx_PUBLIC_KEY_BYTES)[:],
+ ffi.buffer(secret_key, crypto_kx_SECRET_KEY_BYTES)[:],
+ )
+
+
+def crypto_kx_seed_keypair(seed: bytes) -> Tuple[bytes, bytes]:
+ """
+ Generate a keypair with a given seed.
+ This is functionally the same as crypto_box_seed_keypair, however
+ it uses the blake2b hash primitive instead of sha512.
+ It is included mainly for api consistency when using crypto_kx.
+ :param seed: random seed
+ :type seed: bytes
+ :return: (public_key, secret_key)
+ :rtype: (bytes, bytes)
+ """
+ public_key = ffi.new("unsigned char[]", crypto_kx_PUBLIC_KEY_BYTES)
+ secret_key = ffi.new("unsigned char[]", crypto_kx_SECRET_KEY_BYTES)
+ ensure(
+ isinstance(seed, bytes) and len(seed) == crypto_kx_SEED_BYTES,
+ "Seed must be a {} byte long bytes sequence".format(
+ crypto_kx_SEED_BYTES
+ ),
+ raising=exc.TypeError,
+ )
+ res = lib.crypto_kx_seed_keypair(public_key, secret_key, seed)
+ ensure(res == 0, "Key generation failed.", raising=exc.CryptoError)
+
+ return (
+ ffi.buffer(public_key, crypto_kx_PUBLIC_KEY_BYTES)[:],
+ ffi.buffer(secret_key, crypto_kx_SECRET_KEY_BYTES)[:],
+ )
+
+
+def crypto_kx_client_session_keys(
+ client_public_key: bytes,
+ client_secret_key: bytes,
+ server_public_key: bytes,
+) -> Tuple[bytes, bytes]:
+ """
+ Generate session keys for the client.
+ :param client_public_key:
+ :type client_public_key: bytes
+ :param client_secret_key:
+ :type client_secret_key: bytes
+ :param server_public_key:
+ :type server_public_key: bytes
+ :return: (rx_key, tx_key)
+ :rtype: (bytes, bytes)
+ """
+ ensure(
+ isinstance(client_public_key, bytes)
+ and len(client_public_key) == crypto_kx_PUBLIC_KEY_BYTES,
+ "Client public key must be a {} bytes long bytes sequence".format(
+ crypto_kx_PUBLIC_KEY_BYTES
+ ),
+ raising=exc.TypeError,
+ )
+ ensure(
+ isinstance(client_secret_key, bytes)
+ and len(client_secret_key) == crypto_kx_SECRET_KEY_BYTES,
+ "Client secret key must be a {} bytes long bytes sequence".format(
+ crypto_kx_PUBLIC_KEY_BYTES
+ ),
+ raising=exc.TypeError,
+ )
+ ensure(
+ isinstance(server_public_key, bytes)
+ and len(server_public_key) == crypto_kx_PUBLIC_KEY_BYTES,
+ "Server public key must be a {} bytes long bytes sequence".format(
+ crypto_kx_PUBLIC_KEY_BYTES
+ ),
+ raising=exc.TypeError,
+ )
+
+ rx_key = ffi.new("unsigned char[]", crypto_kx_SESSION_KEY_BYTES)
+ tx_key = ffi.new("unsigned char[]", crypto_kx_SESSION_KEY_BYTES)
+ res = lib.crypto_kx_client_session_keys(
+ rx_key, tx_key, client_public_key, client_secret_key, server_public_key
+ )
+ ensure(
+ res == 0,
+ "Client session key generation failed.",
+ raising=exc.CryptoError,
+ )
+
+ return (
+ ffi.buffer(rx_key, crypto_kx_SESSION_KEY_BYTES)[:],
+ ffi.buffer(tx_key, crypto_kx_SESSION_KEY_BYTES)[:],
+ )
+
+
+def crypto_kx_server_session_keys(
+ server_public_key: bytes,
+ server_secret_key: bytes,
+ client_public_key: bytes,
+) -> Tuple[bytes, bytes]:
+ """
+ Generate session keys for the server.
+ :param server_public_key:
+ :type server_public_key: bytes
+ :param server_secret_key:
+ :type server_secret_key: bytes
+ :param client_public_key:
+ :type client_public_key: bytes
+ :return: (rx_key, tx_key)
+ :rtype: (bytes, bytes)
+ """
+ ensure(
+ isinstance(server_public_key, bytes)
+ and len(server_public_key) == crypto_kx_PUBLIC_KEY_BYTES,
+ "Server public key must be a {} bytes long bytes sequence".format(
+ crypto_kx_PUBLIC_KEY_BYTES
+ ),
+ raising=exc.TypeError,
+ )
+ ensure(
+ isinstance(server_secret_key, bytes)
+ and len(server_secret_key) == crypto_kx_SECRET_KEY_BYTES,
+ "Server secret key must be a {} bytes long bytes sequence".format(
+ crypto_kx_PUBLIC_KEY_BYTES
+ ),
+ raising=exc.TypeError,
+ )
+ ensure(
+ isinstance(client_public_key, bytes)
+ and len(client_public_key) == crypto_kx_PUBLIC_KEY_BYTES,
+ "Client public key must be a {} bytes long bytes sequence".format(
+ crypto_kx_PUBLIC_KEY_BYTES
+ ),
+ raising=exc.TypeError,
+ )
+
+ rx_key = ffi.new("unsigned char[]", crypto_kx_SESSION_KEY_BYTES)
+ tx_key = ffi.new("unsigned char[]", crypto_kx_SESSION_KEY_BYTES)
+ res = lib.crypto_kx_server_session_keys(
+ rx_key, tx_key, server_public_key, server_secret_key, client_public_key
+ )
+ ensure(
+ res == 0,
+ "Server session key generation failed.",
+ raising=exc.CryptoError,
+ )
+
+ return (
+ ffi.buffer(rx_key, crypto_kx_SESSION_KEY_BYTES)[:],
+ ffi.buffer(tx_key, crypto_kx_SESSION_KEY_BYTES)[:],
+ )
diff --git a/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_pwhash.py b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_pwhash.py
new file mode 100644
index 00000000..0c4cc1a2
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_pwhash.py
@@ -0,0 +1,600 @@
+# Copyright 2013 Donald Stufft and individual contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys
+from typing import Tuple
+
+import nacl.exceptions as exc
+from nacl._sodium import ffi, lib
+from nacl.exceptions import ensure
+
+
+has_crypto_pwhash_scryptsalsa208sha256 = bool(
+ lib.PYNACL_HAS_CRYPTO_PWHASH_SCRYPTSALSA208SHA256
+)
+
+crypto_pwhash_scryptsalsa208sha256_STRPREFIX = b""
+crypto_pwhash_scryptsalsa208sha256_SALTBYTES = 0
+crypto_pwhash_scryptsalsa208sha256_STRBYTES = 0
+crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN = 0
+crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX = 0
+crypto_pwhash_scryptsalsa208sha256_BYTES_MIN = 0
+crypto_pwhash_scryptsalsa208sha256_BYTES_MAX = 0
+crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN = 0
+crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX = 0
+crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN = 0
+crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX = 0
+crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE = 0
+crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE = 0
+crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE = 0
+crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE = 0
+
+if has_crypto_pwhash_scryptsalsa208sha256:
+ crypto_pwhash_scryptsalsa208sha256_STRPREFIX = ffi.string(
+ ffi.cast("char *", lib.crypto_pwhash_scryptsalsa208sha256_strprefix())
+ )[:]
+ crypto_pwhash_scryptsalsa208sha256_SALTBYTES = (
+ lib.crypto_pwhash_scryptsalsa208sha256_saltbytes()
+ )
+ crypto_pwhash_scryptsalsa208sha256_STRBYTES = (
+ lib.crypto_pwhash_scryptsalsa208sha256_strbytes()
+ )
+ crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN = (
+ lib.crypto_pwhash_scryptsalsa208sha256_passwd_min()
+ )
+ crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX = (
+ lib.crypto_pwhash_scryptsalsa208sha256_passwd_max()
+ )
+ crypto_pwhash_scryptsalsa208sha256_BYTES_MIN = (
+ lib.crypto_pwhash_scryptsalsa208sha256_bytes_min()
+ )
+ crypto_pwhash_scryptsalsa208sha256_BYTES_MAX = (
+ lib.crypto_pwhash_scryptsalsa208sha256_bytes_max()
+ )
+ crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN = (
+ lib.crypto_pwhash_scryptsalsa208sha256_memlimit_min()
+ )
+ crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX = (
+ lib.crypto_pwhash_scryptsalsa208sha256_memlimit_max()
+ )
+ crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN = (
+ lib.crypto_pwhash_scryptsalsa208sha256_opslimit_min()
+ )
+ crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX = (
+ lib.crypto_pwhash_scryptsalsa208sha256_opslimit_max()
+ )
+ crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE = (
+ lib.crypto_pwhash_scryptsalsa208sha256_opslimit_interactive()
+ )
+ crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE = (
+ lib.crypto_pwhash_scryptsalsa208sha256_memlimit_interactive()
+ )
+ crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE = (
+ lib.crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive()
+ )
+ crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE = (
+ lib.crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive()
+ )
+
+crypto_pwhash_ALG_ARGON2I13: int = lib.crypto_pwhash_alg_argon2i13()
+crypto_pwhash_ALG_ARGON2ID13: int = lib.crypto_pwhash_alg_argon2id13()
+crypto_pwhash_ALG_DEFAULT: int = lib.crypto_pwhash_alg_default()
+
+crypto_pwhash_SALTBYTES: int = lib.crypto_pwhash_saltbytes()
+crypto_pwhash_STRBYTES: int = lib.crypto_pwhash_strbytes()
+
+crypto_pwhash_PASSWD_MIN: int = lib.crypto_pwhash_passwd_min()
+crypto_pwhash_PASSWD_MAX: int = lib.crypto_pwhash_passwd_max()
+crypto_pwhash_BYTES_MIN: int = lib.crypto_pwhash_bytes_min()
+crypto_pwhash_BYTES_MAX: int = lib.crypto_pwhash_bytes_max()
+
+crypto_pwhash_argon2i_STRPREFIX: bytes = ffi.string(
+ ffi.cast("char *", lib.crypto_pwhash_argon2i_strprefix())
+)[:]
+crypto_pwhash_argon2i_MEMLIMIT_MIN: int = (
+ lib.crypto_pwhash_argon2i_memlimit_min()
+)
+crypto_pwhash_argon2i_MEMLIMIT_MAX: int = (
+ lib.crypto_pwhash_argon2i_memlimit_max()
+)
+crypto_pwhash_argon2i_OPSLIMIT_MIN: int = (
+ lib.crypto_pwhash_argon2i_opslimit_min()
+)
+crypto_pwhash_argon2i_OPSLIMIT_MAX: int = (
+ lib.crypto_pwhash_argon2i_opslimit_max()
+)
+crypto_pwhash_argon2i_OPSLIMIT_INTERACTIVE: int = (
+ lib.crypto_pwhash_argon2i_opslimit_interactive()
+)
+crypto_pwhash_argon2i_MEMLIMIT_INTERACTIVE: int = (
+ lib.crypto_pwhash_argon2i_memlimit_interactive()
+)
+crypto_pwhash_argon2i_OPSLIMIT_MODERATE: int = (
+ lib.crypto_pwhash_argon2i_opslimit_moderate()
+)
+crypto_pwhash_argon2i_MEMLIMIT_MODERATE: int = (
+ lib.crypto_pwhash_argon2i_memlimit_moderate()
+)
+crypto_pwhash_argon2i_OPSLIMIT_SENSITIVE: int = (
+ lib.crypto_pwhash_argon2i_opslimit_sensitive()
+)
+crypto_pwhash_argon2i_MEMLIMIT_SENSITIVE: int = (
+ lib.crypto_pwhash_argon2i_memlimit_sensitive()
+)
+
+crypto_pwhash_argon2id_STRPREFIX: bytes = ffi.string(
+ ffi.cast("char *", lib.crypto_pwhash_argon2id_strprefix())
+)[:]
+crypto_pwhash_argon2id_MEMLIMIT_MIN: int = (
+ lib.crypto_pwhash_argon2id_memlimit_min()
+)
+crypto_pwhash_argon2id_MEMLIMIT_MAX: int = (
+ lib.crypto_pwhash_argon2id_memlimit_max()
+)
+crypto_pwhash_argon2id_OPSLIMIT_MIN: int = (
+ lib.crypto_pwhash_argon2id_opslimit_min()
+)
+crypto_pwhash_argon2id_OPSLIMIT_MAX: int = (
+ lib.crypto_pwhash_argon2id_opslimit_max()
+)
+crypto_pwhash_argon2id_OPSLIMIT_INTERACTIVE: int = (
+ lib.crypto_pwhash_argon2id_opslimit_interactive()
+)
+crypto_pwhash_argon2id_MEMLIMIT_INTERACTIVE: int = (
+ lib.crypto_pwhash_argon2id_memlimit_interactive()
+)
+crypto_pwhash_argon2id_OPSLIMIT_MODERATE: int = (
+ lib.crypto_pwhash_argon2id_opslimit_moderate()
+)
+crypto_pwhash_argon2id_MEMLIMIT_MODERATE: int = (
+ lib.crypto_pwhash_argon2id_memlimit_moderate()
+)
+crypto_pwhash_argon2id_OPSLIMIT_SENSITIVE: int = (
+ lib.crypto_pwhash_argon2id_opslimit_sensitive()
+)
+crypto_pwhash_argon2id_MEMLIMIT_SENSITIVE: int = (
+ lib.crypto_pwhash_argon2id_memlimit_sensitive()
+)
+
+SCRYPT_OPSLIMIT_INTERACTIVE = (
+ crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE
+)
+SCRYPT_MEMLIMIT_INTERACTIVE = (
+ crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE
+)
+SCRYPT_OPSLIMIT_SENSITIVE = (
+ crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE
+)
+SCRYPT_MEMLIMIT_SENSITIVE = (
+ crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE
+)
+SCRYPT_SALTBYTES = crypto_pwhash_scryptsalsa208sha256_SALTBYTES
+SCRYPT_STRBYTES = crypto_pwhash_scryptsalsa208sha256_STRBYTES
+
+SCRYPT_PR_MAX = (1 << 30) - 1
+LOG2_UINT64_MAX = 63
+UINT64_MAX = (1 << 64) - 1
+SCRYPT_MAX_MEM = 32 * (1024 * 1024)
+
+
+def _check_memory_occupation(
+ n: int, r: int, p: int, maxmem: int = SCRYPT_MAX_MEM
+) -> None:
+ ensure(r != 0, "Invalid block size", raising=exc.ValueError)
+
+ ensure(p != 0, "Invalid parallelization factor", raising=exc.ValueError)
+
+ ensure(
+ (n & (n - 1)) == 0,
+ "Cost factor must be a power of 2",
+ raising=exc.ValueError,
+ )
+
+ ensure(n > 1, "Cost factor must be at least 2", raising=exc.ValueError)
+
+ ensure(
+ p <= SCRYPT_PR_MAX / r,
+ "p*r is greater than {}".format(SCRYPT_PR_MAX),
+ raising=exc.ValueError,
+ )
+
+ ensure(n < (1 << (16 * r)), raising=exc.ValueError)
+
+ Blen = p * 128 * r
+
+ i = UINT64_MAX / 128
+
+ ensure(n + 2 <= i / r, raising=exc.ValueError)
+
+ Vlen = 32 * r * (n + 2) * 4
+
+ ensure(Blen <= UINT64_MAX - Vlen, raising=exc.ValueError)
+
+ ensure(Blen <= sys.maxsize - Vlen, raising=exc.ValueError)
+
+ ensure(
+ Blen + Vlen <= maxmem,
+ "Memory limit would be exceeded with the choosen n, r, p",
+ raising=exc.ValueError,
+ )
+
+
+def nacl_bindings_pick_scrypt_params(
+ opslimit: int, memlimit: int
+) -> Tuple[int, int, int]:
+ """Python implementation of libsodium's pickparams"""
+
+ if opslimit < 32768:
+ opslimit = 32768
+
+ r = 8
+
+ if opslimit < (memlimit // 32):
+ p = 1
+ maxn = opslimit // (4 * r)
+ for n_log2 in range(1, 63): # pragma: no branch
+ if (2 ** n_log2) > (maxn // 2):
+ break
+ else:
+ maxn = memlimit // (r * 128)
+ for n_log2 in range(1, 63): # pragma: no branch
+ if (2 ** n_log2) > maxn // 2:
+ break
+
+ maxrp = (opslimit // 4) // (2 ** n_log2)
+
+ if maxrp > 0x3FFFFFFF: # pragma: no cover
+ maxrp = 0x3FFFFFFF
+
+ p = maxrp // r
+
+ return n_log2, r, p
+
+
+def crypto_pwhash_scryptsalsa208sha256_ll(
+ passwd: bytes,
+ salt: bytes,
+ n: int,
+ r: int,
+ p: int,
+ dklen: int = 64,
+ maxmem: int = SCRYPT_MAX_MEM,
+) -> bytes:
+ """
+ Derive a cryptographic key using the ``passwd`` and ``salt``
+ given as input.
+
+ The work factor can be tuned by by picking different
+ values for the parameters
+
+ :param bytes passwd:
+ :param bytes salt:
+ :param bytes salt: *must* be *exactly* :py:const:`.SALTBYTES` long
+ :param int dklen:
+ :param int opslimit:
+ :param int n:
+ :param int r: block size,
+ :param int p: the parallelism factor
+ :param int maxmem: the maximum available memory available for scrypt's
+ operations
+ :rtype: bytes
+ :raises nacl.exceptions.UnavailableError: If called when using a
+ minimal build of libsodium.
+ """
+ ensure(
+ has_crypto_pwhash_scryptsalsa208sha256,
+ "Not available in minimal build",
+ raising=exc.UnavailableError,
+ )
+
+ ensure(isinstance(n, int), raising=TypeError)
+ ensure(isinstance(r, int), raising=TypeError)
+ ensure(isinstance(p, int), raising=TypeError)
+
+ ensure(isinstance(passwd, bytes), raising=TypeError)
+ ensure(isinstance(salt, bytes), raising=TypeError)
+
+ _check_memory_occupation(n, r, p, maxmem)
+
+ buf = ffi.new("uint8_t[]", dklen)
+
+ ret = lib.crypto_pwhash_scryptsalsa208sha256_ll(
+ passwd, len(passwd), salt, len(salt), n, r, p, buf, dklen
+ )
+
+ ensure(
+ ret == 0,
+ "Unexpected failure in key derivation",
+ raising=exc.RuntimeError,
+ )
+
+ return ffi.buffer(ffi.cast("char *", buf), dklen)[:]
+
+
+def crypto_pwhash_scryptsalsa208sha256_str(
+ passwd: bytes,
+ opslimit: int = SCRYPT_OPSLIMIT_INTERACTIVE,
+ memlimit: int = SCRYPT_MEMLIMIT_INTERACTIVE,
+) -> bytes:
+ """
+ Derive a cryptographic key using the ``passwd`` and ``salt``
+ given as input, returning a string representation which includes
+ the salt and the tuning parameters.
+
+ The returned string can be directly stored as a password hash.
+
+ See :py:func:`.crypto_pwhash_scryptsalsa208sha256` for a short
+ discussion about ``opslimit`` and ``memlimit`` values.
+
+ :param bytes passwd:
+ :param int opslimit:
+ :param int memlimit:
+ :return: serialized key hash, including salt and tuning parameters
+ :rtype: bytes
+ :raises nacl.exceptions.UnavailableError: If called when using a
+ minimal build of libsodium.
+ """
+ ensure(
+ has_crypto_pwhash_scryptsalsa208sha256,
+ "Not available in minimal build",
+ raising=exc.UnavailableError,
+ )
+
+ buf = ffi.new("char[]", SCRYPT_STRBYTES)
+
+ ret = lib.crypto_pwhash_scryptsalsa208sha256_str(
+ buf, passwd, len(passwd), opslimit, memlimit
+ )
+
+ ensure(
+ ret == 0,
+ "Unexpected failure in password hashing",
+ raising=exc.RuntimeError,
+ )
+
+ return ffi.string(buf)
+
+
+def crypto_pwhash_scryptsalsa208sha256_str_verify(
+ passwd_hash: bytes, passwd: bytes
+) -> bool:
+ """
+ Verifies the ``passwd`` against the ``passwd_hash`` that was generated.
+ Returns True or False depending on the success
+
+ :param passwd_hash: bytes
+ :param passwd: bytes
+ :rtype: boolean
+ :raises nacl.exceptions.UnavailableError: If called when using a
+ minimal build of libsodium.
+ """
+ ensure(
+ has_crypto_pwhash_scryptsalsa208sha256,
+ "Not available in minimal build",
+ raising=exc.UnavailableError,
+ )
+
+ ensure(
+ len(passwd_hash) == SCRYPT_STRBYTES - 1,
+ "Invalid password hash",
+ raising=exc.ValueError,
+ )
+
+ ret = lib.crypto_pwhash_scryptsalsa208sha256_str_verify(
+ passwd_hash, passwd, len(passwd)
+ )
+ ensure(ret == 0, "Wrong password", raising=exc.InvalidkeyError)
+ # all went well, therefore:
+ return True
+
+
+def _check_argon2_limits_alg(opslimit: int, memlimit: int, alg: int) -> None:
+
+ if alg == crypto_pwhash_ALG_ARGON2I13:
+ if memlimit < crypto_pwhash_argon2i_MEMLIMIT_MIN:
+ raise exc.ValueError(
+ "memlimit must be at least {} bytes".format(
+ crypto_pwhash_argon2i_MEMLIMIT_MIN
+ )
+ )
+ elif memlimit > crypto_pwhash_argon2i_MEMLIMIT_MAX:
+ raise exc.ValueError(
+ "memlimit must be at most {} bytes".format(
+ crypto_pwhash_argon2i_MEMLIMIT_MAX
+ )
+ )
+ if opslimit < crypto_pwhash_argon2i_OPSLIMIT_MIN:
+ raise exc.ValueError(
+ "opslimit must be at least {}".format(
+ crypto_pwhash_argon2i_OPSLIMIT_MIN
+ )
+ )
+ elif opslimit > crypto_pwhash_argon2i_OPSLIMIT_MAX:
+ raise exc.ValueError(
+ "opslimit must be at most {}".format(
+ crypto_pwhash_argon2i_OPSLIMIT_MAX
+ )
+ )
+
+ elif alg == crypto_pwhash_ALG_ARGON2ID13:
+ if memlimit < crypto_pwhash_argon2id_MEMLIMIT_MIN:
+ raise exc.ValueError(
+ "memlimit must be at least {} bytes".format(
+ crypto_pwhash_argon2id_MEMLIMIT_MIN
+ )
+ )
+ elif memlimit > crypto_pwhash_argon2id_MEMLIMIT_MAX:
+ raise exc.ValueError(
+ "memlimit must be at most {} bytes".format(
+ crypto_pwhash_argon2id_MEMLIMIT_MAX
+ )
+ )
+ if opslimit < crypto_pwhash_argon2id_OPSLIMIT_MIN:
+ raise exc.ValueError(
+ "opslimit must be at least {}".format(
+ crypto_pwhash_argon2id_OPSLIMIT_MIN
+ )
+ )
+ elif opslimit > crypto_pwhash_argon2id_OPSLIMIT_MAX:
+ raise exc.ValueError(
+ "opslimit must be at most {}".format(
+ crypto_pwhash_argon2id_OPSLIMIT_MAX
+ )
+ )
+ else:
+ raise exc.TypeError("Unsupported algorithm")
+
+
+def crypto_pwhash_alg(
+ outlen: int,
+ passwd: bytes,
+ salt: bytes,
+ opslimit: int,
+ memlimit: int,
+ alg: int,
+) -> bytes:
+ """
+ Derive a raw cryptographic key using the ``passwd`` and the ``salt``
+ given as input to the ``alg`` algorithm.
+
+ :param outlen: the length of the derived key
+ :type outlen: int
+ :param passwd: The input password
+ :type passwd: bytes
+ :param salt:
+ :type salt: bytes
+ :param opslimit: computational cost
+ :type opslimit: int
+ :param memlimit: memory cost
+ :type memlimit: int
+ :param alg: algorithm identifier
+ :type alg: int
+ :return: derived key
+ :rtype: bytes
+ """
+ ensure(isinstance(outlen, int), raising=exc.TypeError)
+ ensure(isinstance(opslimit, int), raising=exc.TypeError)
+ ensure(isinstance(memlimit, int), raising=exc.TypeError)
+ ensure(isinstance(alg, int), raising=exc.TypeError)
+ ensure(isinstance(passwd, bytes), raising=exc.TypeError)
+
+ if len(salt) != crypto_pwhash_SALTBYTES:
+ raise exc.ValueError(
+ "salt must be exactly {} bytes long".format(
+ crypto_pwhash_SALTBYTES
+ )
+ )
+
+ if outlen < crypto_pwhash_BYTES_MIN:
+ raise exc.ValueError(
+ "derived key must be at least {} bytes long".format(
+ crypto_pwhash_BYTES_MIN
+ )
+ )
+
+ elif outlen > crypto_pwhash_BYTES_MAX:
+ raise exc.ValueError(
+ "derived key must be at most {} bytes long".format(
+ crypto_pwhash_BYTES_MAX
+ )
+ )
+
+ _check_argon2_limits_alg(opslimit, memlimit, alg)
+
+ outbuf = ffi.new("unsigned char[]", outlen)
+
+ ret = lib.crypto_pwhash(
+ outbuf, outlen, passwd, len(passwd), salt, opslimit, memlimit, alg
+ )
+
+ ensure(
+ ret == 0,
+ "Unexpected failure in key derivation",
+ raising=exc.RuntimeError,
+ )
+
+ return ffi.buffer(outbuf, outlen)[:]
+
+
+def crypto_pwhash_str_alg(
+ passwd: bytes,
+ opslimit: int,
+ memlimit: int,
+ alg: int,
+) -> bytes:
+ """
+ Derive a cryptographic key using the ``passwd`` given as input
+ and a random salt, returning a string representation which
+ includes the salt, the tuning parameters and the used algorithm.
+
+ :param passwd: The input password
+ :type passwd: bytes
+ :param opslimit: computational cost
+ :type opslimit: int
+ :param memlimit: memory cost
+ :type memlimit: int
+ :param alg: The algorithm to use
+ :type alg: int
+ :return: serialized derived key and parameters
+ :rtype: bytes
+ """
+ ensure(isinstance(opslimit, int), raising=TypeError)
+ ensure(isinstance(memlimit, int), raising=TypeError)
+ ensure(isinstance(passwd, bytes), raising=TypeError)
+
+ _check_argon2_limits_alg(opslimit, memlimit, alg)
+
+ outbuf = ffi.new("char[]", 128)
+
+ ret = lib.crypto_pwhash_str_alg(
+ outbuf, passwd, len(passwd), opslimit, memlimit, alg
+ )
+
+ ensure(
+ ret == 0,
+ "Unexpected failure in key derivation",
+ raising=exc.RuntimeError,
+ )
+
+ return ffi.string(outbuf)
+
+
+def crypto_pwhash_str_verify(passwd_hash: bytes, passwd: bytes) -> bool:
+ """
+ Verifies the ``passwd`` against a given password hash.
+
+ Returns True on success, raises InvalidkeyError on failure
+ :param passwd_hash: saved password hash
+ :type passwd_hash: bytes
+ :param passwd: password to be checked
+ :type passwd: bytes
+ :return: success
+ :rtype: boolean
+ """
+ ensure(isinstance(passwd_hash, bytes), raising=TypeError)
+ ensure(isinstance(passwd, bytes), raising=TypeError)
+ ensure(
+ len(passwd_hash) <= 127,
+ "Hash must be at most 127 bytes long",
+ raising=exc.ValueError,
+ )
+
+ ret = lib.crypto_pwhash_str_verify(passwd_hash, passwd, len(passwd))
+
+ ensure(ret == 0, "Wrong password", raising=exc.InvalidkeyError)
+ # all went well, therefore:
+ return True
+
+
+crypto_pwhash_argon2i_str_verify = crypto_pwhash_str_verify
diff --git a/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_scalarmult.py b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_scalarmult.py
new file mode 100644
index 00000000..ca4a2819
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_scalarmult.py
@@ -0,0 +1,240 @@
+# Copyright 2013-2018 Donald Stufft and individual contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+from nacl import exceptions as exc
+from nacl._sodium import ffi, lib
+from nacl.exceptions import ensure
+
+
+has_crypto_scalarmult_ed25519 = bool(lib.PYNACL_HAS_CRYPTO_SCALARMULT_ED25519)
+
+crypto_scalarmult_BYTES: int = lib.crypto_scalarmult_bytes()
+crypto_scalarmult_SCALARBYTES: int = lib.crypto_scalarmult_scalarbytes()
+
+crypto_scalarmult_ed25519_BYTES = 0
+crypto_scalarmult_ed25519_SCALARBYTES = 0
+
+if has_crypto_scalarmult_ed25519:
+ crypto_scalarmult_ed25519_BYTES = lib.crypto_scalarmult_ed25519_bytes()
+ crypto_scalarmult_ed25519_SCALARBYTES = (
+ lib.crypto_scalarmult_ed25519_scalarbytes()
+ )
+
+
+def crypto_scalarmult_base(n: bytes) -> bytes:
+ """
+ Computes and returns the scalar product of a standard group element and an
+ integer ``n``.
+
+ :param n: bytes
+ :rtype: bytes
+ """
+ q = ffi.new("unsigned char[]", crypto_scalarmult_BYTES)
+
+ rc = lib.crypto_scalarmult_base(q, n)
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+
+ return ffi.buffer(q, crypto_scalarmult_SCALARBYTES)[:]
+
+
+def crypto_scalarmult(n: bytes, p: bytes) -> bytes:
+ """
+ Computes and returns the scalar product of the given group element and an
+ integer ``n``.
+
+ :param p: bytes
+ :param n: bytes
+ :rtype: bytes
+ """
+ q = ffi.new("unsigned char[]", crypto_scalarmult_BYTES)
+
+ rc = lib.crypto_scalarmult(q, n, p)
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+
+ return ffi.buffer(q, crypto_scalarmult_SCALARBYTES)[:]
+
+
+def crypto_scalarmult_ed25519_base(n: bytes) -> bytes:
+ """
+ Computes and returns the scalar product of a standard group element and an
+ integer ``n`` on the edwards25519 curve.
+
+ :param n: a :py:data:`.crypto_scalarmult_ed25519_SCALARBYTES` long bytes
+ sequence representing a scalar
+ :type n: bytes
+ :return: a point on the edwards25519 curve, represented as a
+ :py:data:`.crypto_scalarmult_ed25519_BYTES` long bytes sequence
+ :rtype: bytes
+ :raises nacl.exceptions.UnavailableError: If called when using a
+ minimal build of libsodium.
+ """
+ ensure(
+ has_crypto_scalarmult_ed25519,
+ "Not available in minimal build",
+ raising=exc.UnavailableError,
+ )
+
+ ensure(
+ isinstance(n, bytes)
+ and len(n) == crypto_scalarmult_ed25519_SCALARBYTES,
+ "Input must be a {} long bytes sequence".format(
+ "crypto_scalarmult_ed25519_SCALARBYTES"
+ ),
+ raising=exc.TypeError,
+ )
+
+ q = ffi.new("unsigned char[]", crypto_scalarmult_ed25519_BYTES)
+
+ rc = lib.crypto_scalarmult_ed25519_base(q, n)
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+
+ return ffi.buffer(q, crypto_scalarmult_ed25519_BYTES)[:]
+
+
+def crypto_scalarmult_ed25519_base_noclamp(n: bytes) -> bytes:
+ """
+ Computes and returns the scalar product of a standard group element and an
+ integer ``n`` on the edwards25519 curve. The integer ``n`` is not clamped.
+
+ :param n: a :py:data:`.crypto_scalarmult_ed25519_SCALARBYTES` long bytes
+ sequence representing a scalar
+ :type n: bytes
+ :return: a point on the edwards25519 curve, represented as a
+ :py:data:`.crypto_scalarmult_ed25519_BYTES` long bytes sequence
+ :rtype: bytes
+ :raises nacl.exceptions.UnavailableError: If called when using a
+ minimal build of libsodium.
+ """
+ ensure(
+ has_crypto_scalarmult_ed25519,
+ "Not available in minimal build",
+ raising=exc.UnavailableError,
+ )
+
+ ensure(
+ isinstance(n, bytes)
+ and len(n) == crypto_scalarmult_ed25519_SCALARBYTES,
+ "Input must be a {} long bytes sequence".format(
+ "crypto_scalarmult_ed25519_SCALARBYTES"
+ ),
+ raising=exc.TypeError,
+ )
+
+ q = ffi.new("unsigned char[]", crypto_scalarmult_ed25519_BYTES)
+
+ rc = lib.crypto_scalarmult_ed25519_base_noclamp(q, n)
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+
+ return ffi.buffer(q, crypto_scalarmult_ed25519_BYTES)[:]
+
+
+def crypto_scalarmult_ed25519(n: bytes, p: bytes) -> bytes:
+ """
+ Computes and returns the scalar product of a *clamped* integer ``n``
+ and the given group element on the edwards25519 curve.
+ The scalar is clamped, as done in the public key generation case,
+ by setting to zero the bits in position [0, 1, 2, 255] and setting
+ to one the bit in position 254.
+
+ :param n: a :py:data:`.crypto_scalarmult_ed25519_SCALARBYTES` long bytes
+ sequence representing a scalar
+ :type n: bytes
+ :param p: a :py:data:`.crypto_scalarmult_ed25519_BYTES` long bytes sequence
+ representing a point on the edwards25519 curve
+ :type p: bytes
+ :return: a point on the edwards25519 curve, represented as a
+ :py:data:`.crypto_scalarmult_ed25519_BYTES` long bytes sequence
+ :rtype: bytes
+ :raises nacl.exceptions.UnavailableError: If called when using a
+ minimal build of libsodium.
+ """
+ ensure(
+ has_crypto_scalarmult_ed25519,
+ "Not available in minimal build",
+ raising=exc.UnavailableError,
+ )
+
+ ensure(
+ isinstance(n, bytes)
+ and len(n) == crypto_scalarmult_ed25519_SCALARBYTES,
+ "Input must be a {} long bytes sequence".format(
+ "crypto_scalarmult_ed25519_SCALARBYTES"
+ ),
+ raising=exc.TypeError,
+ )
+
+ ensure(
+ isinstance(p, bytes) and len(p) == crypto_scalarmult_ed25519_BYTES,
+ "Input must be a {} long bytes sequence".format(
+ "crypto_scalarmult_ed25519_BYTES"
+ ),
+ raising=exc.TypeError,
+ )
+
+ q = ffi.new("unsigned char[]", crypto_scalarmult_ed25519_BYTES)
+
+ rc = lib.crypto_scalarmult_ed25519(q, n, p)
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+
+ return ffi.buffer(q, crypto_scalarmult_ed25519_BYTES)[:]
+
+
+def crypto_scalarmult_ed25519_noclamp(n: bytes, p: bytes) -> bytes:
+ """
+ Computes and returns the scalar product of an integer ``n``
+ and the given group element on the edwards25519 curve. The integer
+ ``n`` is not clamped.
+
+ :param n: a :py:data:`.crypto_scalarmult_ed25519_SCALARBYTES` long bytes
+ sequence representing a scalar
+ :type n: bytes
+ :param p: a :py:data:`.crypto_scalarmult_ed25519_BYTES` long bytes sequence
+ representing a point on the edwards25519 curve
+ :type p: bytes
+ :return: a point on the edwards25519 curve, represented as a
+ :py:data:`.crypto_scalarmult_ed25519_BYTES` long bytes sequence
+ :rtype: bytes
+ :raises nacl.exceptions.UnavailableError: If called when using a
+ minimal build of libsodium.
+ """
+ ensure(
+ has_crypto_scalarmult_ed25519,
+ "Not available in minimal build",
+ raising=exc.UnavailableError,
+ )
+
+ ensure(
+ isinstance(n, bytes)
+ and len(n) == crypto_scalarmult_ed25519_SCALARBYTES,
+ "Input must be a {} long bytes sequence".format(
+ "crypto_scalarmult_ed25519_SCALARBYTES"
+ ),
+ raising=exc.TypeError,
+ )
+
+ ensure(
+ isinstance(p, bytes) and len(p) == crypto_scalarmult_ed25519_BYTES,
+ "Input must be a {} long bytes sequence".format(
+ "crypto_scalarmult_ed25519_BYTES"
+ ),
+ raising=exc.TypeError,
+ )
+
+ q = ffi.new("unsigned char[]", crypto_scalarmult_ed25519_BYTES)
+
+ rc = lib.crypto_scalarmult_ed25519_noclamp(q, n, p)
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+
+ return ffi.buffer(q, crypto_scalarmult_ed25519_BYTES)[:]
diff --git a/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_secretbox.py b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_secretbox.py
new file mode 100644
index 00000000..2a632a2b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_secretbox.py
@@ -0,0 +1,86 @@
+# Copyright 2013 Donald Stufft and individual contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+from nacl import exceptions as exc
+from nacl._sodium import ffi, lib
+from nacl.exceptions import ensure
+
+
+crypto_secretbox_KEYBYTES: int = lib.crypto_secretbox_keybytes()
+crypto_secretbox_NONCEBYTES: int = lib.crypto_secretbox_noncebytes()
+crypto_secretbox_ZEROBYTES: int = lib.crypto_secretbox_zerobytes()
+crypto_secretbox_BOXZEROBYTES: int = lib.crypto_secretbox_boxzerobytes()
+crypto_secretbox_MACBYTES: int = lib.crypto_secretbox_macbytes()
+crypto_secretbox_MESSAGEBYTES_MAX: int = (
+ lib.crypto_secretbox_messagebytes_max()
+)
+
+
+def crypto_secretbox(message: bytes, nonce: bytes, key: bytes) -> bytes:
+ """
+ Encrypts and returns the message ``message`` with the secret ``key`` and
+ the nonce ``nonce``.
+
+ :param message: bytes
+ :param nonce: bytes
+ :param key: bytes
+ :rtype: bytes
+ """
+ if len(key) != crypto_secretbox_KEYBYTES:
+ raise exc.ValueError("Invalid key")
+
+ if len(nonce) != crypto_secretbox_NONCEBYTES:
+ raise exc.ValueError("Invalid nonce")
+
+ padded = b"\x00" * crypto_secretbox_ZEROBYTES + message
+ ciphertext = ffi.new("unsigned char[]", len(padded))
+
+ res = lib.crypto_secretbox(ciphertext, padded, len(padded), nonce, key)
+ ensure(res == 0, "Encryption failed", raising=exc.CryptoError)
+
+ ciphertext = ffi.buffer(ciphertext, len(padded))
+ return ciphertext[crypto_secretbox_BOXZEROBYTES:]
+
+
+def crypto_secretbox_open(
+ ciphertext: bytes, nonce: bytes, key: bytes
+) -> bytes:
+ """
+ Decrypt and returns the encrypted message ``ciphertext`` with the secret
+ ``key`` and the nonce ``nonce``.
+
+ :param ciphertext: bytes
+ :param nonce: bytes
+ :param key: bytes
+ :rtype: bytes
+ """
+ if len(key) != crypto_secretbox_KEYBYTES:
+ raise exc.ValueError("Invalid key")
+
+ if len(nonce) != crypto_secretbox_NONCEBYTES:
+ raise exc.ValueError("Invalid nonce")
+
+ padded = b"\x00" * crypto_secretbox_BOXZEROBYTES + ciphertext
+ plaintext = ffi.new("unsigned char[]", len(padded))
+
+ res = lib.crypto_secretbox_open(plaintext, padded, len(padded), nonce, key)
+ ensure(
+ res == 0,
+ "Decryption failed. Ciphertext failed verification",
+ raising=exc.CryptoError,
+ )
+
+ plaintext = ffi.buffer(plaintext, len(padded))
+ return plaintext[crypto_secretbox_ZEROBYTES:]
diff --git a/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_secretstream.py b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_secretstream.py
new file mode 100644
index 00000000..d7c6725e
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_secretstream.py
@@ -0,0 +1,357 @@
+# Copyright 2013-2018 Donald Stufft and individual contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from typing import ByteString, Optional, Tuple, cast
+
+from nacl import exceptions as exc
+from nacl._sodium import ffi, lib
+from nacl.exceptions import ensure
+
+
+crypto_secretstream_xchacha20poly1305_ABYTES: int = (
+ lib.crypto_secretstream_xchacha20poly1305_abytes()
+)
+crypto_secretstream_xchacha20poly1305_HEADERBYTES: int = (
+ lib.crypto_secretstream_xchacha20poly1305_headerbytes()
+)
+crypto_secretstream_xchacha20poly1305_KEYBYTES: int = (
+ lib.crypto_secretstream_xchacha20poly1305_keybytes()
+)
+crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX: int = (
+ lib.crypto_secretstream_xchacha20poly1305_messagebytes_max()
+)
+crypto_secretstream_xchacha20poly1305_STATEBYTES: int = (
+ lib.crypto_secretstream_xchacha20poly1305_statebytes()
+)
+
+
+crypto_secretstream_xchacha20poly1305_TAG_MESSAGE: int = (
+ lib.crypto_secretstream_xchacha20poly1305_tag_message()
+)
+crypto_secretstream_xchacha20poly1305_TAG_PUSH: int = (
+ lib.crypto_secretstream_xchacha20poly1305_tag_push()
+)
+crypto_secretstream_xchacha20poly1305_TAG_REKEY: int = (
+ lib.crypto_secretstream_xchacha20poly1305_tag_rekey()
+)
+crypto_secretstream_xchacha20poly1305_TAG_FINAL: int = (
+ lib.crypto_secretstream_xchacha20poly1305_tag_final()
+)
+
+
+def crypto_secretstream_xchacha20poly1305_keygen() -> bytes:
+ """
+ Generate a key for use with
+ :func:`.crypto_secretstream_xchacha20poly1305_init_push`.
+
+ """
+ keybuf = ffi.new(
+ "unsigned char[]",
+ crypto_secretstream_xchacha20poly1305_KEYBYTES,
+ )
+ lib.crypto_secretstream_xchacha20poly1305_keygen(keybuf)
+ return ffi.buffer(keybuf)[:]
+
+
+class crypto_secretstream_xchacha20poly1305_state:
+ """
+ An object wrapping the crypto_secretstream_xchacha20poly1305 state.
+
+ """
+
+ __slots__ = ["statebuf", "rawbuf", "tagbuf"]
+
+ def __init__(self) -> None:
+ """Initialize a clean state object."""
+ self.statebuf: ByteString = ffi.new(
+ "unsigned char[]",
+ crypto_secretstream_xchacha20poly1305_STATEBYTES,
+ )
+
+ self.rawbuf: Optional[ByteString] = None
+ self.tagbuf: Optional[ByteString] = None
+
+
+def crypto_secretstream_xchacha20poly1305_init_push(
+ state: crypto_secretstream_xchacha20poly1305_state, key: bytes
+) -> bytes:
+ """
+ Initialize a crypto_secretstream_xchacha20poly1305 encryption buffer.
+
+ :param state: a secretstream state object
+ :type state: crypto_secretstream_xchacha20poly1305_state
+ :param key: must be
+ :data:`.crypto_secretstream_xchacha20poly1305_KEYBYTES` long
+ :type key: bytes
+ :return: header
+ :rtype: bytes
+
+ """
+ ensure(
+ isinstance(state, crypto_secretstream_xchacha20poly1305_state),
+ "State must be a crypto_secretstream_xchacha20poly1305_state object",
+ raising=exc.TypeError,
+ )
+ ensure(
+ isinstance(key, bytes),
+ "Key must be a bytes sequence",
+ raising=exc.TypeError,
+ )
+ ensure(
+ len(key) == crypto_secretstream_xchacha20poly1305_KEYBYTES,
+ "Invalid key length",
+ raising=exc.ValueError,
+ )
+
+ headerbuf = ffi.new(
+ "unsigned char []",
+ crypto_secretstream_xchacha20poly1305_HEADERBYTES,
+ )
+
+ rc = lib.crypto_secretstream_xchacha20poly1305_init_push(
+ state.statebuf, headerbuf, key
+ )
+ ensure(rc == 0, "Unexpected failure", raising=exc.RuntimeError)
+
+ return ffi.buffer(headerbuf)[:]
+
+
+def crypto_secretstream_xchacha20poly1305_push(
+ state: crypto_secretstream_xchacha20poly1305_state,
+ m: bytes,
+ ad: Optional[bytes] = None,
+ tag: int = crypto_secretstream_xchacha20poly1305_TAG_MESSAGE,
+) -> bytes:
+ """
+ Add an encrypted message to the secret stream.
+
+ :param state: a secretstream state object
+ :type state: crypto_secretstream_xchacha20poly1305_state
+ :param m: the message to encrypt, the maximum length of an individual
+ message is
+ :data:`.crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX`.
+ :type m: bytes
+ :param ad: additional data to include in the authentication tag
+ :type ad: bytes or None
+ :param tag: the message tag, usually
+ :data:`.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE` or
+ :data:`.crypto_secretstream_xchacha20poly1305_TAG_FINAL`.
+ :type tag: int
+ :return: ciphertext
+ :rtype: bytes
+
+ """
+ ensure(
+ isinstance(state, crypto_secretstream_xchacha20poly1305_state),
+ "State must be a crypto_secretstream_xchacha20poly1305_state object",
+ raising=exc.TypeError,
+ )
+ ensure(isinstance(m, bytes), "Message is not bytes", raising=exc.TypeError)
+ ensure(
+ len(m) <= crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX,
+ "Message is too long",
+ raising=exc.ValueError,
+ )
+ ensure(
+ ad is None or isinstance(ad, bytes),
+ "Additional data must be bytes or None",
+ raising=exc.TypeError,
+ )
+
+ clen = len(m) + crypto_secretstream_xchacha20poly1305_ABYTES
+ if state.rawbuf is None or len(state.rawbuf) < clen:
+ state.rawbuf = ffi.new("unsigned char[]", clen)
+
+ if ad is None:
+ ad = ffi.NULL
+ adlen = 0
+ else:
+ adlen = len(ad)
+
+ rc = lib.crypto_secretstream_xchacha20poly1305_push(
+ state.statebuf,
+ state.rawbuf,
+ ffi.NULL,
+ m,
+ len(m),
+ ad,
+ adlen,
+ tag,
+ )
+ ensure(rc == 0, "Unexpected failure", raising=exc.RuntimeError)
+
+ return ffi.buffer(state.rawbuf, clen)[:]
+
+
+def crypto_secretstream_xchacha20poly1305_init_pull(
+ state: crypto_secretstream_xchacha20poly1305_state,
+ header: bytes,
+ key: bytes,
+) -> None:
+ """
+ Initialize a crypto_secretstream_xchacha20poly1305 decryption buffer.
+
+ :param state: a secretstream state object
+ :type state: crypto_secretstream_xchacha20poly1305_state
+ :param header: must be
+ :data:`.crypto_secretstream_xchacha20poly1305_HEADERBYTES` long
+ :type header: bytes
+ :param key: must be
+ :data:`.crypto_secretstream_xchacha20poly1305_KEYBYTES` long
+ :type key: bytes
+
+ """
+ ensure(
+ isinstance(state, crypto_secretstream_xchacha20poly1305_state),
+ "State must be a crypto_secretstream_xchacha20poly1305_state object",
+ raising=exc.TypeError,
+ )
+ ensure(
+ isinstance(header, bytes),
+ "Header must be a bytes sequence",
+ raising=exc.TypeError,
+ )
+ ensure(
+ len(header) == crypto_secretstream_xchacha20poly1305_HEADERBYTES,
+ "Invalid header length",
+ raising=exc.ValueError,
+ )
+ ensure(
+ isinstance(key, bytes),
+ "Key must be a bytes sequence",
+ raising=exc.TypeError,
+ )
+ ensure(
+ len(key) == crypto_secretstream_xchacha20poly1305_KEYBYTES,
+ "Invalid key length",
+ raising=exc.ValueError,
+ )
+
+ if state.tagbuf is None:
+ state.tagbuf = ffi.new("unsigned char *")
+
+ rc = lib.crypto_secretstream_xchacha20poly1305_init_pull(
+ state.statebuf, header, key
+ )
+ ensure(rc == 0, "Unexpected failure", raising=exc.RuntimeError)
+
+
+def crypto_secretstream_xchacha20poly1305_pull(
+ state: crypto_secretstream_xchacha20poly1305_state,
+ c: bytes,
+ ad: Optional[bytes] = None,
+) -> Tuple[bytes, int]:
+ """
+ Read a decrypted message from the secret stream.
+
+ :param state: a secretstream state object
+ :type state: crypto_secretstream_xchacha20poly1305_state
+ :param c: the ciphertext to decrypt, the maximum length of an individual
+ ciphertext is
+ :data:`.crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX` +
+ :data:`.crypto_secretstream_xchacha20poly1305_ABYTES`.
+ :type c: bytes
+ :param ad: additional data to include in the authentication tag
+ :type ad: bytes or None
+ :return: (message, tag)
+ :rtype: (bytes, int)
+
+ """
+ ensure(
+ isinstance(state, crypto_secretstream_xchacha20poly1305_state),
+ "State must be a crypto_secretstream_xchacha20poly1305_state object",
+ raising=exc.TypeError,
+ )
+ ensure(
+ state.tagbuf is not None,
+ (
+ "State must be initialized using "
+ "crypto_secretstream_xchacha20poly1305_init_pull"
+ ),
+ raising=exc.ValueError,
+ )
+ ensure(
+ isinstance(c, bytes),
+ "Ciphertext is not bytes",
+ raising=exc.TypeError,
+ )
+ ensure(
+ len(c) >= crypto_secretstream_xchacha20poly1305_ABYTES,
+ "Ciphertext is too short",
+ raising=exc.ValueError,
+ )
+ ensure(
+ len(c)
+ <= (
+ crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX
+ + crypto_secretstream_xchacha20poly1305_ABYTES
+ ),
+ "Ciphertext is too long",
+ raising=exc.ValueError,
+ )
+ ensure(
+ ad is None or isinstance(ad, bytes),
+ "Additional data must be bytes or None",
+ raising=exc.TypeError,
+ )
+
+ mlen = len(c) - crypto_secretstream_xchacha20poly1305_ABYTES
+ if state.rawbuf is None or len(state.rawbuf) < mlen:
+ state.rawbuf = ffi.new("unsigned char[]", mlen)
+
+ if ad is None:
+ ad = ffi.NULL
+ adlen = 0
+ else:
+ adlen = len(ad)
+
+ rc = lib.crypto_secretstream_xchacha20poly1305_pull(
+ state.statebuf,
+ state.rawbuf,
+ ffi.NULL,
+ state.tagbuf,
+ c,
+ len(c),
+ ad,
+ adlen,
+ )
+ ensure(rc == 0, "Unexpected failure", raising=exc.RuntimeError)
+
+ # Cast safety: we `ensure` above that `state.tagbuf is not None`.
+ return (
+ ffi.buffer(state.rawbuf, mlen)[:],
+ int(cast(bytes, state.tagbuf)[0]),
+ )
+
+
+def crypto_secretstream_xchacha20poly1305_rekey(
+ state: crypto_secretstream_xchacha20poly1305_state,
+) -> None:
+ """
+ Explicitly change the encryption key in the stream.
+
+ Normally the stream is re-keyed as needed or an explicit ``tag`` of
+ :data:`.crypto_secretstream_xchacha20poly1305_TAG_REKEY` is added to a
+ message to ensure forward secrecy, but this method can be used instead
+ if the re-keying is controlled without adding the tag.
+
+ :param state: a secretstream state object
+ :type state: crypto_secretstream_xchacha20poly1305_state
+
+ """
+ ensure(
+ isinstance(state, crypto_secretstream_xchacha20poly1305_state),
+ "State must be a crypto_secretstream_xchacha20poly1305_state object",
+ raising=exc.TypeError,
+ )
+ lib.crypto_secretstream_xchacha20poly1305_rekey(state.statebuf)
diff --git a/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_shorthash.py b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_shorthash.py
new file mode 100644
index 00000000..8f7d209e
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_shorthash.py
@@ -0,0 +1,81 @@
+# Copyright 2016 Donald Stufft and individual contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+import nacl.exceptions as exc
+from nacl._sodium import ffi, lib
+from nacl.exceptions import ensure
+
+
+has_crypto_shorthash_siphashx24 = bool(
+ lib.PYNACL_HAS_CRYPTO_SHORTHASH_SIPHASHX24
+)
+
+BYTES: int = lib.crypto_shorthash_siphash24_bytes()
+KEYBYTES: int = lib.crypto_shorthash_siphash24_keybytes()
+
+XBYTES = 0
+XKEYBYTES = 0
+
+if has_crypto_shorthash_siphashx24:
+ XBYTES = lib.crypto_shorthash_siphashx24_bytes()
+ XKEYBYTES = lib.crypto_shorthash_siphashx24_keybytes()
+
+
+def crypto_shorthash_siphash24(data: bytes, key: bytes) -> bytes:
+ """Compute a fast, cryptographic quality, keyed hash of the input data
+
+ :param data:
+ :type data: bytes
+ :param key: len(key) must be equal to
+ :py:data:`.KEYBYTES` (16)
+ :type key: bytes
+ """
+ if len(key) != KEYBYTES:
+ raise exc.ValueError(
+ "Key length must be exactly {} bytes".format(KEYBYTES)
+ )
+ digest = ffi.new("unsigned char[]", BYTES)
+ rc = lib.crypto_shorthash_siphash24(digest, data, len(data), key)
+
+ ensure(rc == 0, raising=exc.RuntimeError)
+ return ffi.buffer(digest, BYTES)[:]
+
+
+def crypto_shorthash_siphashx24(data: bytes, key: bytes) -> bytes:
+ """Compute a fast, cryptographic quality, keyed hash of the input data
+
+ :param data:
+ :type data: bytes
+ :param key: len(key) must be equal to
+ :py:data:`.XKEYBYTES` (16)
+ :type key: bytes
+ :raises nacl.exceptions.UnavailableError: If called when using a
+ minimal build of libsodium.
+ """
+ ensure(
+ has_crypto_shorthash_siphashx24,
+ "Not available in minimal build",
+ raising=exc.UnavailableError,
+ )
+
+ if len(key) != XKEYBYTES:
+ raise exc.ValueError(
+ "Key length must be exactly {} bytes".format(XKEYBYTES)
+ )
+ digest = ffi.new("unsigned char[]", XBYTES)
+ rc = lib.crypto_shorthash_siphashx24(digest, data, len(data), key)
+
+ ensure(rc == 0, raising=exc.RuntimeError)
+ return ffi.buffer(digest, XBYTES)[:]
diff --git a/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_sign.py b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_sign.py
new file mode 100644
index 00000000..de3be47a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/nacl/bindings/crypto_sign.py
@@ -0,0 +1,327 @@
+# Copyright 2013 Donald Stufft and individual contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from typing import Tuple
+
+from nacl import exceptions as exc
+from nacl._sodium import ffi, lib
+from nacl.exceptions import ensure
+
+
+crypto_sign_BYTES: int = lib.crypto_sign_bytes()
+# crypto_sign_SEEDBYTES = lib.crypto_sign_seedbytes()
+crypto_sign_SEEDBYTES: int = lib.crypto_sign_secretkeybytes() // 2
+crypto_sign_PUBLICKEYBYTES: int = lib.crypto_sign_publickeybytes()
+crypto_sign_SECRETKEYBYTES: int = lib.crypto_sign_secretkeybytes()
+
+crypto_sign_curve25519_BYTES: int = lib.crypto_box_secretkeybytes()
+
+crypto_sign_ed25519ph_STATEBYTES: int = lib.crypto_sign_ed25519ph_statebytes()
+
+
+def crypto_sign_keypair() -> Tuple[bytes, bytes]:
+ """
+ Returns a randomly generated public key and secret key.
+
+ :rtype: (bytes(public_key), bytes(secret_key))
+ """
+ pk = ffi.new("unsigned char[]", crypto_sign_PUBLICKEYBYTES)
+ sk = ffi.new("unsigned char[]", crypto_sign_SECRETKEYBYTES)
+
+ rc = lib.crypto_sign_keypair(pk, sk)
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+
+ return (
+ ffi.buffer(pk, crypto_sign_PUBLICKEYBYTES)[:],
+ ffi.buffer(sk, crypto_sign_SECRETKEYBYTES)[:],
+ )
+
+
+def crypto_sign_seed_keypair(seed: bytes) -> Tuple[bytes, bytes]:
+ """
+ Computes and returns the public key and secret key using the seed ``seed``.
+
+ :param seed: bytes
+ :rtype: (bytes(public_key), bytes(secret_key))
+ """
+ if len(seed) != crypto_sign_SEEDBYTES:
+ raise exc.ValueError("Invalid seed")
+
+ pk = ffi.new("unsigned char[]", crypto_sign_PUBLICKEYBYTES)
+ sk = ffi.new("unsigned char[]", crypto_sign_SECRETKEYBYTES)
+
+ rc = lib.crypto_sign_seed_keypair(pk, sk, seed)
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+
+ return (
+ ffi.buffer(pk, crypto_sign_PUBLICKEYBYTES)[:],
+ ffi.buffer(sk, crypto_sign_SECRETKEYBYTES)[:],
+ )
+
+
+def crypto_sign(message: bytes, sk: bytes) -> bytes:
+ """
+ Signs the message ``message`` using the secret key ``sk`` and returns the
+ signed message.
+
+ :param message: bytes
+ :param sk: bytes
+ :rtype: bytes
+ """
+ signed = ffi.new("unsigned char[]", len(message) + crypto_sign_BYTES)
+ signed_len = ffi.new("unsigned long long *")
+
+ rc = lib.crypto_sign(signed, signed_len, message, len(message), sk)
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+
+ return ffi.buffer(signed, signed_len[0])[:]
+
+
+def crypto_sign_open(signed: bytes, pk: bytes) -> bytes:
+ """
+ Verifies the signature of the signed message ``signed`` using the public
+ key ``pk`` and returns the unsigned message.
+
+ :param signed: bytes
+ :param pk: bytes
+ :rtype: bytes
+ """
+ message = ffi.new("unsigned char[]", len(signed))
+ message_len = ffi.new("unsigned long long *")
+
+ if (
+ lib.crypto_sign_open(message, message_len, signed, len(signed), pk)
+ != 0
+ ):
+ raise exc.BadSignatureError("Signature was forged or corrupt")
+
+ return ffi.buffer(message, message_len[0])[:]
+
+
+def crypto_sign_ed25519_pk_to_curve25519(public_key_bytes: bytes) -> bytes:
+ """
+ Converts a public Ed25519 key (encoded as bytes ``public_key_bytes``) to
+ a public Curve25519 key as bytes.
+
+ Raises a ValueError if ``public_key_bytes`` is not of length
+ ``crypto_sign_PUBLICKEYBYTES``
+
+ :param public_key_bytes: bytes
+ :rtype: bytes
+ """
+ if len(public_key_bytes) != crypto_sign_PUBLICKEYBYTES:
+ raise exc.ValueError("Invalid curve public key")
+
+ curve_public_key_len = crypto_sign_curve25519_BYTES
+ curve_public_key = ffi.new("unsigned char[]", curve_public_key_len)
+
+ rc = lib.crypto_sign_ed25519_pk_to_curve25519(
+ curve_public_key, public_key_bytes
+ )
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+
+ return ffi.buffer(curve_public_key, curve_public_key_len)[:]
+
+
+def crypto_sign_ed25519_sk_to_curve25519(secret_key_bytes: bytes) -> bytes:
+ """
+ Converts a secret Ed25519 key (encoded as bytes ``secret_key_bytes``) to
+ a secret Curve25519 key as bytes.
+
+ Raises a ValueError if ``secret_key_bytes``is not of length
+ ``crypto_sign_SECRETKEYBYTES``
+
+ :param secret_key_bytes: bytes
+ :rtype: bytes
+ """
+ if len(secret_key_bytes) != crypto_sign_SECRETKEYBYTES:
+ raise exc.ValueError("Invalid curve secret key")
+
+ curve_secret_key_len = crypto_sign_curve25519_BYTES
+ curve_secret_key = ffi.new("unsigned char[]", curve_secret_key_len)
+
+ rc = lib.crypto_sign_ed25519_sk_to_curve25519(
+ curve_secret_key, secret_key_bytes
+ )
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+
+ return ffi.buffer(curve_secret_key, curve_secret_key_len)[:]
+
+
+def crypto_sign_ed25519_sk_to_pk(secret_key_bytes: bytes) -> bytes:
+ """
+ Extract the public Ed25519 key from a secret Ed25519 key (encoded
+ as bytes ``secret_key_bytes``).
+
+ Raises a ValueError if ``secret_key_bytes``is not of length
+ ``crypto_sign_SECRETKEYBYTES``
+
+ :param secret_key_bytes: bytes
+ :rtype: bytes
+ """
+ if len(secret_key_bytes) != crypto_sign_SECRETKEYBYTES:
+ raise exc.ValueError("Invalid secret key")
+
+ return secret_key_bytes[crypto_sign_SEEDBYTES:]
+
+
+def crypto_sign_ed25519_sk_to_seed(secret_key_bytes: bytes) -> bytes:
+ """
+ Extract the seed from a secret Ed25519 key (encoded
+ as bytes ``secret_key_bytes``).
+
+ Raises a ValueError if ``secret_key_bytes``is not of length
+ ``crypto_sign_SECRETKEYBYTES``
+
+ :param secret_key_bytes: bytes
+ :rtype: bytes
+ """
+ if len(secret_key_bytes) != crypto_sign_SECRETKEYBYTES:
+ raise exc.ValueError("Invalid secret key")
+
+ return secret_key_bytes[:crypto_sign_SEEDBYTES]
+
+
+class crypto_sign_ed25519ph_state:
+ """
+ State object wrapping the sha-512 state used in ed25519ph computation
+ """
+
+ __slots__ = ["state"]
+
+ def __init__(self) -> None:
+ self.state: bytes = ffi.new(
+ "unsigned char[]", crypto_sign_ed25519ph_STATEBYTES
+ )
+
+ rc = lib.crypto_sign_ed25519ph_init(self.state)
+
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+
+
+def crypto_sign_ed25519ph_update(
+ edph: crypto_sign_ed25519ph_state, pmsg: bytes
+) -> None:
+ """
+ Update the hash state wrapped in edph
+
+ :param edph: the ed25519ph state being updated
+ :type edph: crypto_sign_ed25519ph_state
+ :param pmsg: the partial message
+ :type pmsg: bytes
+ :rtype: None
+ """
+ ensure(
+ isinstance(edph, crypto_sign_ed25519ph_state),
+ "edph parameter must be a ed25519ph_state object",
+ raising=exc.TypeError,
+ )
+ ensure(
+ isinstance(pmsg, bytes),
+ "pmsg parameter must be a bytes object",
+ raising=exc.TypeError,
+ )
+ rc = lib.crypto_sign_ed25519ph_update(edph.state, pmsg, len(pmsg))
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+
+
+def crypto_sign_ed25519ph_final_create(
+ edph: crypto_sign_ed25519ph_state, sk: bytes
+) -> bytes:
+ """
+ Create a signature for the data hashed in edph
+ using the secret key sk
+
+ :param edph: the ed25519ph state for the data
+ being signed
+ :type edph: crypto_sign_ed25519ph_state
+ :param sk: the ed25519 secret part of the signing key
+ :type sk: bytes
+ :return: ed25519ph signature
+ :rtype: bytes
+ """
+ ensure(
+ isinstance(edph, crypto_sign_ed25519ph_state),
+ "edph parameter must be a ed25519ph_state object",
+ raising=exc.TypeError,
+ )
+ ensure(
+ isinstance(sk, bytes),
+ "secret key parameter must be a bytes object",
+ raising=exc.TypeError,
+ )
+ ensure(
+ len(sk) == crypto_sign_SECRETKEYBYTES,
+ ("secret key must be {} bytes long").format(
+ crypto_sign_SECRETKEYBYTES
+ ),
+ raising=exc.TypeError,
+ )
+ signature = ffi.new("unsigned char[]", crypto_sign_BYTES)
+ rc = lib.crypto_sign_ed25519ph_final_create(
+ edph.state, signature, ffi.NULL, sk
+ )
+ ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
+
+ return ffi.buffer(signature, crypto_sign_BYTES)[:]
+
+
+def crypto_sign_ed25519ph_final_verify(
+ edph: crypto_sign_ed25519ph_state, signature: bytes, pk: bytes
+) -> bool:
+ """
+ Verify a prehashed signature using the public key pk
+
+ :param edph: the ed25519ph state for the data
+ being verified
+ :type edph: crypto_sign_ed25519ph_state
+ :param signature: the signature being verified
+ :type signature: bytes
+ :param pk: the ed25519 public part of the signing key
+ :type pk: bytes
+ :return: True if the signature is valid
+ :rtype: boolean
+ :raises exc.BadSignatureError: if the signature is not valid
+ """
+ ensure(
+ isinstance(edph, crypto_sign_ed25519ph_state),
+ "edph parameter must be a ed25519ph_state object",
+ raising=exc.TypeError,
+ )
+ ensure(
+ isinstance(signature, bytes),
+ "signature parameter must be a bytes object",
+ raising=exc.TypeError,
+ )
+ ensure(
+ len(signature) == crypto_sign_BYTES,
+ ("signature must be {} bytes long").format(crypto_sign_BYTES),
+ raising=exc.TypeError,
+ )
+ ensure(
+ isinstance(pk, bytes),
+ "public key parameter must be a bytes object",
+ raising=exc.TypeError,
+ )
+ ensure(
+ len(pk) == crypto_sign_PUBLICKEYBYTES,
+ ("public key must be {} bytes long").format(
+ crypto_sign_PUBLICKEYBYTES
+ ),
+ raising=exc.TypeError,
+ )
+ rc = lib.crypto_sign_ed25519ph_final_verify(edph.state, signature, pk)
+ if rc != 0:
+ raise exc.BadSignatureError("Signature was forged or corrupt")
+
+ return True
diff --git a/.venv/lib/python3.12/site-packages/nacl/bindings/randombytes.py b/.venv/lib/python3.12/site-packages/nacl/bindings/randombytes.py
new file mode 100644
index 00000000..ed76deb5
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/nacl/bindings/randombytes.py
@@ -0,0 +1,51 @@
+# Copyright 2013 Donald Stufft and individual contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+from nacl import exceptions as exc
+from nacl._sodium import ffi, lib
+
+randombytes_SEEDBYTES: int = lib.randombytes_seedbytes()
+
+
+def randombytes(size: int) -> bytes:
+ """
+ Returns ``size`` number of random bytes from a cryptographically secure
+ random source.
+
+ :param size: int
+ :rtype: bytes
+ """
+ buf = ffi.new("unsigned char[]", size)
+ lib.randombytes(buf, size)
+ return ffi.buffer(buf, size)[:]
+
+
+def randombytes_buf_deterministic(size: int, seed: bytes) -> bytes:
+ """
+ Returns ``size`` number of deterministically generated pseudorandom bytes
+ from a seed
+
+ :param size: int
+ :param seed: bytes
+ :rtype: bytes
+ """
+ if len(seed) != randombytes_SEEDBYTES:
+ raise exc.TypeError(
+ "Deterministic random bytes must be generated from 32 bytes"
+ )
+
+ buf = ffi.new("unsigned char[]", size)
+ lib.randombytes_buf_deterministic(buf, size, seed)
+ return ffi.buffer(buf, size)[:]
diff --git a/.venv/lib/python3.12/site-packages/nacl/bindings/sodium_core.py b/.venv/lib/python3.12/site-packages/nacl/bindings/sodium_core.py
new file mode 100644
index 00000000..7ebb84c8
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/nacl/bindings/sodium_core.py
@@ -0,0 +1,33 @@
+# Copyright 2013 Donald Stufft and individual contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from nacl import exceptions as exc
+from nacl._sodium import ffi, lib
+from nacl.exceptions import ensure
+
+
+def _sodium_init() -> None:
+ ensure(
+ lib.sodium_init() != -1,
+ "Could not initialize sodium",
+ raising=exc.RuntimeError,
+ )
+
+
+def sodium_init() -> None:
+ """
+ Initializes sodium, picking the best implementations available for this
+ machine.
+ """
+ ffi.init_once(_sodium_init, "libsodium")
diff --git a/.venv/lib/python3.12/site-packages/nacl/bindings/utils.py b/.venv/lib/python3.12/site-packages/nacl/bindings/utils.py
new file mode 100644
index 00000000..0ff22e34
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/nacl/bindings/utils.py
@@ -0,0 +1,141 @@
+# Copyright 2013-2017 Donald Stufft and individual contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import nacl.exceptions as exc
+from nacl._sodium import ffi, lib
+from nacl.exceptions import ensure
+
+
+def sodium_memcmp(inp1: bytes, inp2: bytes) -> bool:
+ """
+ Compare contents of two memory regions in constant time
+ """
+ ensure(isinstance(inp1, bytes), raising=exc.TypeError)
+ ensure(isinstance(inp2, bytes), raising=exc.TypeError)
+
+ ln = max(len(inp1), len(inp2))
+
+ buf1 = ffi.new("char []", ln)
+ buf2 = ffi.new("char []", ln)
+
+ ffi.memmove(buf1, inp1, len(inp1))
+ ffi.memmove(buf2, inp2, len(inp2))
+
+ eqL = len(inp1) == len(inp2)
+ eqC = lib.sodium_memcmp(buf1, buf2, ln) == 0
+
+ return eqL and eqC
+
+
+def sodium_pad(s: bytes, blocksize: int) -> bytes:
+ """
+ Pad the input bytearray ``s`` to a multiple of ``blocksize``
+ using the ISO/IEC 7816-4 algorithm
+
+ :param s: input bytes string
+ :type s: bytes
+ :param blocksize:
+ :type blocksize: int
+ :return: padded string
+ :rtype: bytes
+ """
+ ensure(isinstance(s, bytes), raising=exc.TypeError)
+ ensure(isinstance(blocksize, int), raising=exc.TypeError)
+ if blocksize <= 0:
+ raise exc.ValueError
+ s_len = len(s)
+ m_len = s_len + blocksize
+ buf = ffi.new("unsigned char []", m_len)
+ p_len = ffi.new("size_t []", 1)
+ ffi.memmove(buf, s, s_len)
+ rc = lib.sodium_pad(p_len, buf, s_len, blocksize, m_len)
+ ensure(rc == 0, "Padding failure", raising=exc.CryptoError)
+ return ffi.buffer(buf, p_len[0])[:]
+
+
+def sodium_unpad(s: bytes, blocksize: int) -> bytes:
+ """
+ Remove ISO/IEC 7816-4 padding from the input byte array ``s``
+
+ :param s: input bytes string
+ :type s: bytes
+ :param blocksize:
+ :type blocksize: int
+ :return: unpadded string
+ :rtype: bytes
+ """
+ ensure(isinstance(s, bytes), raising=exc.TypeError)
+ ensure(isinstance(blocksize, int), raising=exc.TypeError)
+ s_len = len(s)
+ u_len = ffi.new("size_t []", 1)
+ rc = lib.sodium_unpad(u_len, s, s_len, blocksize)
+ if rc != 0:
+ raise exc.CryptoError("Unpadding failure")
+ return s[: u_len[0]]
+
+
+def sodium_increment(inp: bytes) -> bytes:
+ """
+ Increment the value of a byte-sequence interpreted
+ as the little-endian representation of a unsigned big integer.
+
+ :param inp: input bytes buffer
+ :type inp: bytes
+ :return: a byte-sequence representing, as a little-endian
+ unsigned big integer, the value ``to_int(inp)``
+ incremented by one.
+ :rtype: bytes
+
+ """
+ ensure(isinstance(inp, bytes), raising=exc.TypeError)
+
+ ln = len(inp)
+ buf = ffi.new("unsigned char []", ln)
+
+ ffi.memmove(buf, inp, ln)
+
+ lib.sodium_increment(buf, ln)
+
+ return ffi.buffer(buf, ln)[:]
+
+
+def sodium_add(a: bytes, b: bytes) -> bytes:
+ """
+ Given a couple of *same-sized* byte sequences, interpreted as the
+ little-endian representation of two unsigned integers, compute
+ the modular addition of the represented values, in constant time for
+ a given common length of the byte sequences.
+
+ :param a: input bytes buffer
+ :type a: bytes
+ :param b: input bytes buffer
+ :type b: bytes
+ :return: a byte-sequence representing, as a little-endian big integer,
+ the integer value of ``(to_int(a) + to_int(b)) mod 2^(8*len(a))``
+ :rtype: bytes
+ """
+ ensure(isinstance(a, bytes), raising=exc.TypeError)
+ ensure(isinstance(b, bytes), raising=exc.TypeError)
+ ln = len(a)
+ ensure(len(b) == ln, raising=exc.TypeError)
+
+ buf_a = ffi.new("unsigned char []", ln)
+ buf_b = ffi.new("unsigned char []", ln)
+
+ ffi.memmove(buf_a, a, ln)
+ ffi.memmove(buf_b, b, ln)
+
+ lib.sodium_add(buf_a, buf_b, ln)
+
+ return ffi.buffer(buf_a, ln)[:]