mirror of
https://gitlab.sectorq.eu/jaydee/omv_backup.git
synced 2025-07-03 08:33:04 +02:00
added v3
This commit is contained in:
39
venv/lib/python3.11/site-packages/nacl/__init__.py
Normal file
39
venv/lib/python3.11/site-packages/nacl/__init__.py
Normal file
@ -0,0 +1,39 @@
|
||||
# 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.
|
||||
|
||||
|
||||
__all__ = [
|
||||
"__title__",
|
||||
"__summary__",
|
||||
"__uri__",
|
||||
"__version__",
|
||||
"__author__",
|
||||
"__email__",
|
||||
"__license__",
|
||||
"__copyright__",
|
||||
]
|
||||
|
||||
__title__ = "PyNaCl"
|
||||
__summary__ = (
|
||||
"Python binding to the Networking and Cryptography (NaCl) library"
|
||||
)
|
||||
__uri__ = "https://github.com/pyca/pynacl/"
|
||||
|
||||
__version__ = "1.5.0"
|
||||
|
||||
__author__ = "The PyNaCl developers"
|
||||
__email__ = "cryptography-dev@python.org"
|
||||
|
||||
__license__ = "Apache License 2.0"
|
||||
__copyright__ = "Copyright 2013-2018 {}".format(__author__)
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
venv/lib/python3.11/site-packages/nacl/_sodium.abi3.so
Executable file
BIN
venv/lib/python3.11/site-packages/nacl/_sodium.abi3.so
Executable file
Binary file not shown.
451
venv/lib/python3.11/site-packages/nacl/bindings/__init__.py
Normal file
451
venv/lib/python3.11/site-packages/nacl/bindings/__init__.py
Normal file
@ -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()
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
559
venv/lib/python3.11/site-packages/nacl/bindings/crypto_aead.py
Normal file
559
venv/lib/python3.11/site-packages/nacl/bindings/crypto_aead.py
Normal file
@ -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])[:]
|
324
venv/lib/python3.11/site-packages/nacl/bindings/crypto_box.py
Normal file
324
venv/lib/python3.11/site-packages/nacl/bindings/crypto_box.py
Normal file
@ -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)[:]
|
412
venv/lib/python3.11/site-packages/nacl/bindings/crypto_core.py
Normal file
412
venv/lib/python3.11/site-packages/nacl/bindings/crypto_core.py
Normal file
@ -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)[:]
|
@ -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)[:]
|
@ -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)[:]
|
200
venv/lib/python3.11/site-packages/nacl/bindings/crypto_kx.py
Normal file
200
venv/lib/python3.11/site-packages/nacl/bindings/crypto_kx.py
Normal file
@ -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)[:],
|
||||
)
|
600
venv/lib/python3.11/site-packages/nacl/bindings/crypto_pwhash.py
Normal file
600
venv/lib/python3.11/site-packages/nacl/bindings/crypto_pwhash.py
Normal file
@ -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
|
@ -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)[:]
|
@ -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:]
|
@ -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)
|
@ -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)[:]
|
327
venv/lib/python3.11/site-packages/nacl/bindings/crypto_sign.py
Normal file
327
venv/lib/python3.11/site-packages/nacl/bindings/crypto_sign.py
Normal file
@ -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
|
@ -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)[:]
|
@ -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")
|
141
venv/lib/python3.11/site-packages/nacl/bindings/utils.py
Normal file
141
venv/lib/python3.11/site-packages/nacl/bindings/utils.py
Normal file
@ -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)[:]
|
105
venv/lib/python3.11/site-packages/nacl/encoding.py
Normal file
105
venv/lib/python3.11/site-packages/nacl/encoding.py
Normal file
@ -0,0 +1,105 @@
|
||||
# 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 base64
|
||||
import binascii
|
||||
from abc import ABCMeta, abstractmethod
|
||||
from typing import SupportsBytes, Type
|
||||
|
||||
|
||||
# TODO: when the minimum supported version of Python is 3.8, we can import
|
||||
# Protocol from typing, and replace Encoder with a Protocol instead.
|
||||
class _Encoder(metaclass=ABCMeta):
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
def encode(data: bytes) -> bytes:
|
||||
"""Transform raw data to encoded data."""
|
||||
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
def decode(data: bytes) -> bytes:
|
||||
"""Transform encoded data back to raw data.
|
||||
|
||||
Decoding after encoding should be a no-op, i.e. `decode(encode(x)) == x`.
|
||||
"""
|
||||
|
||||
|
||||
# Functions that use encoders are passed a subclass of _Encoder, not an instance
|
||||
# (because the methods are all static). Let's gloss over that detail by defining
|
||||
# an alias for Type[_Encoder].
|
||||
Encoder = Type[_Encoder]
|
||||
|
||||
|
||||
class RawEncoder(_Encoder):
|
||||
@staticmethod
|
||||
def encode(data: bytes) -> bytes:
|
||||
return data
|
||||
|
||||
@staticmethod
|
||||
def decode(data: bytes) -> bytes:
|
||||
return data
|
||||
|
||||
|
||||
class HexEncoder(_Encoder):
|
||||
@staticmethod
|
||||
def encode(data: bytes) -> bytes:
|
||||
return binascii.hexlify(data)
|
||||
|
||||
@staticmethod
|
||||
def decode(data: bytes) -> bytes:
|
||||
return binascii.unhexlify(data)
|
||||
|
||||
|
||||
class Base16Encoder(_Encoder):
|
||||
@staticmethod
|
||||
def encode(data: bytes) -> bytes:
|
||||
return base64.b16encode(data)
|
||||
|
||||
@staticmethod
|
||||
def decode(data: bytes) -> bytes:
|
||||
return base64.b16decode(data)
|
||||
|
||||
|
||||
class Base32Encoder(_Encoder):
|
||||
@staticmethod
|
||||
def encode(data: bytes) -> bytes:
|
||||
return base64.b32encode(data)
|
||||
|
||||
@staticmethod
|
||||
def decode(data: bytes) -> bytes:
|
||||
return base64.b32decode(data)
|
||||
|
||||
|
||||
class Base64Encoder(_Encoder):
|
||||
@staticmethod
|
||||
def encode(data: bytes) -> bytes:
|
||||
return base64.b64encode(data)
|
||||
|
||||
@staticmethod
|
||||
def decode(data: bytes) -> bytes:
|
||||
return base64.b64decode(data)
|
||||
|
||||
|
||||
class URLSafeBase64Encoder(_Encoder):
|
||||
@staticmethod
|
||||
def encode(data: bytes) -> bytes:
|
||||
return base64.urlsafe_b64encode(data)
|
||||
|
||||
@staticmethod
|
||||
def decode(data: bytes) -> bytes:
|
||||
return base64.urlsafe_b64decode(data)
|
||||
|
||||
|
||||
class Encodable:
|
||||
def encode(self: SupportsBytes, encoder: Encoder = RawEncoder) -> bytes:
|
||||
return encoder.encode(bytes(self))
|
88
venv/lib/python3.11/site-packages/nacl/exceptions.py
Normal file
88
venv/lib/python3.11/site-packages/nacl/exceptions.py
Normal file
@ -0,0 +1,88 @@
|
||||
# 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.
|
||||
|
||||
|
||||
# We create a clone of various builtin Exception types which additionally
|
||||
# inherit from CryptoError. Below, we refer to the parent types via the
|
||||
# `builtins` namespace, so mypy can distinguish between (e.g.)
|
||||
# `nacl.exceptions.RuntimeError` and `builtins.RuntimeError`.
|
||||
import builtins
|
||||
from typing import Type
|
||||
|
||||
|
||||
class CryptoError(Exception):
|
||||
"""
|
||||
Base exception for all nacl related errors
|
||||
"""
|
||||
|
||||
|
||||
class BadSignatureError(CryptoError):
|
||||
"""
|
||||
Raised when the signature was forged or otherwise corrupt.
|
||||
"""
|
||||
|
||||
|
||||
class RuntimeError(builtins.RuntimeError, CryptoError):
|
||||
pass
|
||||
|
||||
|
||||
class AssertionError(builtins.AssertionError, CryptoError):
|
||||
pass
|
||||
|
||||
|
||||
class TypeError(builtins.TypeError, CryptoError):
|
||||
pass
|
||||
|
||||
|
||||
class ValueError(builtins.ValueError, CryptoError):
|
||||
pass
|
||||
|
||||
|
||||
class InvalidkeyError(CryptoError):
|
||||
pass
|
||||
|
||||
|
||||
class CryptPrefixError(InvalidkeyError):
|
||||
pass
|
||||
|
||||
|
||||
class UnavailableError(RuntimeError):
|
||||
"""
|
||||
is a subclass of :class:`~nacl.exceptions.RuntimeError`, raised when
|
||||
trying to call functions not available in a minimal build of
|
||||
libsodium.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def ensure(cond: bool, *args: object, **kwds: Type[Exception]) -> None:
|
||||
"""
|
||||
Return if a condition is true, otherwise raise a caller-configurable
|
||||
:py:class:`Exception`
|
||||
:param bool cond: the condition to be checked
|
||||
:param sequence args: the arguments to be passed to the exception's
|
||||
constructor
|
||||
The only accepted named parameter is `raising` used to configure the
|
||||
exception to be raised if `cond` is not `True`
|
||||
"""
|
||||
_CHK_UNEXP = "check_condition() got an unexpected keyword argument {0}"
|
||||
|
||||
raising = kwds.pop("raising", AssertionError)
|
||||
if kwds:
|
||||
raise TypeError(_CHK_UNEXP.format(repr(kwds.popitem()[0])))
|
||||
|
||||
if cond is True:
|
||||
return
|
||||
raise raising(*args)
|
182
venv/lib/python3.11/site-packages/nacl/hash.py
Normal file
182
venv/lib/python3.11/site-packages/nacl/hash.py
Normal file
@ -0,0 +1,182 @@
|
||||
# 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.
|
||||
"""
|
||||
The :mod:`nacl.hash` module exposes one-shot interfaces
|
||||
for libsodium selected hash primitives and the constants needed
|
||||
for their usage.
|
||||
"""
|
||||
|
||||
|
||||
import nacl.bindings
|
||||
import nacl.encoding
|
||||
|
||||
|
||||
BLAKE2B_BYTES = nacl.bindings.crypto_generichash_BYTES
|
||||
"""Default digest size for :func:`blake2b` hash"""
|
||||
BLAKE2B_BYTES_MIN = nacl.bindings.crypto_generichash_BYTES_MIN
|
||||
"""Minimum allowed digest size for :func:`blake2b` hash"""
|
||||
BLAKE2B_BYTES_MAX = nacl.bindings.crypto_generichash_BYTES_MAX
|
||||
"""Maximum allowed digest size for :func:`blake2b` hash"""
|
||||
BLAKE2B_KEYBYTES = nacl.bindings.crypto_generichash_KEYBYTES
|
||||
"""Default size of the ``key`` byte array for :func:`blake2b` hash"""
|
||||
BLAKE2B_KEYBYTES_MIN = nacl.bindings.crypto_generichash_KEYBYTES_MIN
|
||||
"""Minimum allowed size of the ``key`` byte array for :func:`blake2b` hash"""
|
||||
BLAKE2B_KEYBYTES_MAX = nacl.bindings.crypto_generichash_KEYBYTES_MAX
|
||||
"""Maximum allowed size of the ``key`` byte array for :func:`blake2b` hash"""
|
||||
BLAKE2B_SALTBYTES = nacl.bindings.crypto_generichash_SALTBYTES
|
||||
"""Maximum allowed length of the ``salt`` byte array for
|
||||
:func:`blake2b` hash"""
|
||||
BLAKE2B_PERSONALBYTES = nacl.bindings.crypto_generichash_PERSONALBYTES
|
||||
"""Maximum allowed length of the ``personalization``
|
||||
byte array for :func:`blake2b` hash"""
|
||||
|
||||
SIPHASH_BYTES = nacl.bindings.crypto_shorthash_siphash24_BYTES
|
||||
"""Size of the :func:`siphash24` digest"""
|
||||
SIPHASH_KEYBYTES = nacl.bindings.crypto_shorthash_siphash24_KEYBYTES
|
||||
"""Size of the secret ``key`` used by the :func:`siphash24` MAC"""
|
||||
|
||||
SIPHASHX_AVAILABLE = nacl.bindings.has_crypto_shorthash_siphashx24
|
||||
"""``True`` if :func:`siphashx24` is available to be called"""
|
||||
|
||||
SIPHASHX_BYTES = nacl.bindings.crypto_shorthash_siphashx24_BYTES
|
||||
"""Size of the :func:`siphashx24` digest"""
|
||||
SIPHASHX_KEYBYTES = nacl.bindings.crypto_shorthash_siphashx24_KEYBYTES
|
||||
"""Size of the secret ``key`` used by the :func:`siphashx24` MAC"""
|
||||
|
||||
_b2b_hash = nacl.bindings.crypto_generichash_blake2b_salt_personal
|
||||
_sip_hash = nacl.bindings.crypto_shorthash_siphash24
|
||||
_sip_hashx = nacl.bindings.crypto_shorthash_siphashx24
|
||||
|
||||
|
||||
def sha256(
|
||||
message: bytes, encoder: nacl.encoding.Encoder = nacl.encoding.HexEncoder
|
||||
) -> bytes:
|
||||
"""
|
||||
Hashes ``message`` with SHA256.
|
||||
|
||||
:param message: The message to hash.
|
||||
:type message: bytes
|
||||
:param encoder: A class that is able to encode the hashed message.
|
||||
:returns: The hashed message.
|
||||
:rtype: bytes
|
||||
"""
|
||||
return encoder.encode(nacl.bindings.crypto_hash_sha256(message))
|
||||
|
||||
|
||||
def sha512(
|
||||
message: bytes, encoder: nacl.encoding.Encoder = nacl.encoding.HexEncoder
|
||||
) -> bytes:
|
||||
"""
|
||||
Hashes ``message`` with SHA512.
|
||||
|
||||
:param message: The message to hash.
|
||||
:type message: bytes
|
||||
:param encoder: A class that is able to encode the hashed message.
|
||||
:returns: The hashed message.
|
||||
:rtype: bytes
|
||||
"""
|
||||
return encoder.encode(nacl.bindings.crypto_hash_sha512(message))
|
||||
|
||||
|
||||
def blake2b(
|
||||
data: bytes,
|
||||
digest_size: int = BLAKE2B_BYTES,
|
||||
key: bytes = b"",
|
||||
salt: bytes = b"",
|
||||
person: bytes = b"",
|
||||
encoder: nacl.encoding.Encoder = nacl.encoding.HexEncoder,
|
||||
) -> bytes:
|
||||
"""
|
||||
Hashes ``data`` with blake2b.
|
||||
|
||||
:param data: the digest input byte sequence
|
||||
:type data: bytes
|
||||
:param digest_size: the requested digest size; must be at most
|
||||
:const:`BLAKE2B_BYTES_MAX`;
|
||||
the default digest size is
|
||||
:const:`BLAKE2B_BYTES`
|
||||
:type digest_size: int
|
||||
:param key: the key to be set for keyed MAC/PRF usage; if set, the key
|
||||
must be at most :data:`~nacl.hash.BLAKE2B_KEYBYTES_MAX` long
|
||||
:type key: bytes
|
||||
:param salt: an initialization salt at most
|
||||
:const:`BLAKE2B_SALTBYTES` long;
|
||||
it will be zero-padded if needed
|
||||
:type salt: bytes
|
||||
:param person: a personalization string at most
|
||||
:const:`BLAKE2B_PERSONALBYTES` long;
|
||||
it will be zero-padded if needed
|
||||
:type person: bytes
|
||||
:param encoder: the encoder to use on returned digest
|
||||
:type encoder: class
|
||||
:returns: The hashed message.
|
||||
:rtype: bytes
|
||||
"""
|
||||
|
||||
digest = _b2b_hash(
|
||||
data, digest_size=digest_size, key=key, salt=salt, person=person
|
||||
)
|
||||
return encoder.encode(digest)
|
||||
|
||||
|
||||
generichash = blake2b
|
||||
|
||||
|
||||
def siphash24(
|
||||
message: bytes,
|
||||
key: bytes = b"",
|
||||
encoder: nacl.encoding.Encoder = nacl.encoding.HexEncoder,
|
||||
) -> bytes:
|
||||
"""
|
||||
Computes a keyed MAC of ``message`` using the short-input-optimized
|
||||
siphash-2-4 construction.
|
||||
|
||||
:param message: The message to hash.
|
||||
:type message: bytes
|
||||
:param key: the message authentication key for the siphash MAC construct
|
||||
:type key: bytes(:const:`SIPHASH_KEYBYTES`)
|
||||
:param encoder: A class that is able to encode the hashed message.
|
||||
:returns: The hashed message.
|
||||
:rtype: bytes(:const:`SIPHASH_BYTES`)
|
||||
"""
|
||||
digest = _sip_hash(message, key)
|
||||
return encoder.encode(digest)
|
||||
|
||||
|
||||
shorthash = siphash24
|
||||
|
||||
|
||||
def siphashx24(
|
||||
message: bytes,
|
||||
key: bytes = b"",
|
||||
encoder: nacl.encoding.Encoder = nacl.encoding.HexEncoder,
|
||||
) -> bytes:
|
||||
"""
|
||||
Computes a keyed MAC of ``message`` using the 128 bit variant of the
|
||||
siphash-2-4 construction.
|
||||
|
||||
:param message: The message to hash.
|
||||
:type message: bytes
|
||||
:param key: the message authentication key for the siphash MAC construct
|
||||
:type key: bytes(:const:`SIPHASHX_KEYBYTES`)
|
||||
:param encoder: A class that is able to encode the hashed message.
|
||||
:returns: The hashed message.
|
||||
:rtype: bytes(:const:`SIPHASHX_BYTES`)
|
||||
:raises nacl.exceptions.UnavailableError: If called when using a
|
||||
minimal build of libsodium.
|
||||
|
||||
.. versionadded:: 1.2
|
||||
"""
|
||||
digest = _sip_hashx(message, key)
|
||||
return encoder.encode(digest)
|
143
venv/lib/python3.11/site-packages/nacl/hashlib.py
Normal file
143
venv/lib/python3.11/site-packages/nacl/hashlib.py
Normal file
@ -0,0 +1,143 @@
|
||||
# Copyright 2016-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.
|
||||
|
||||
|
||||
import binascii
|
||||
from typing import NoReturn
|
||||
|
||||
import nacl.bindings
|
||||
from nacl.utils import bytes_as_string
|
||||
|
||||
BYTES = nacl.bindings.crypto_generichash_BYTES
|
||||
BYTES_MIN = nacl.bindings.crypto_generichash_BYTES_MIN
|
||||
BYTES_MAX = nacl.bindings.crypto_generichash_BYTES_MAX
|
||||
KEYBYTES = nacl.bindings.crypto_generichash_KEYBYTES
|
||||
KEYBYTES_MIN = nacl.bindings.crypto_generichash_KEYBYTES_MIN
|
||||
KEYBYTES_MAX = nacl.bindings.crypto_generichash_KEYBYTES_MAX
|
||||
SALTBYTES = nacl.bindings.crypto_generichash_SALTBYTES
|
||||
PERSONALBYTES = nacl.bindings.crypto_generichash_PERSONALBYTES
|
||||
|
||||
SCRYPT_AVAILABLE = nacl.bindings.has_crypto_pwhash_scryptsalsa208sha256
|
||||
|
||||
_b2b_init = nacl.bindings.crypto_generichash_blake2b_init
|
||||
_b2b_final = nacl.bindings.crypto_generichash_blake2b_final
|
||||
_b2b_update = nacl.bindings.crypto_generichash_blake2b_update
|
||||
|
||||
|
||||
class blake2b:
|
||||
"""
|
||||
:py:mod:`hashlib` API compatible blake2b algorithm implementation
|
||||
"""
|
||||
|
||||
MAX_DIGEST_SIZE = BYTES
|
||||
MAX_KEY_SIZE = KEYBYTES_MAX
|
||||
PERSON_SIZE = PERSONALBYTES
|
||||
SALT_SIZE = SALTBYTES
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
data: bytes = b"",
|
||||
digest_size: int = BYTES,
|
||||
key: bytes = b"",
|
||||
salt: bytes = b"",
|
||||
person: bytes = b"",
|
||||
):
|
||||
"""
|
||||
:py:class:`.blake2b` algorithm initializer
|
||||
|
||||
:param data:
|
||||
:type data: bytes
|
||||
:param int digest_size: the requested digest size; must be
|
||||
at most :py:attr:`.MAX_DIGEST_SIZE`;
|
||||
the default digest size is :py:data:`.BYTES`
|
||||
:param key: the key to be set for keyed MAC/PRF usage; if set,
|
||||
the key must be at most :py:data:`.KEYBYTES_MAX` long
|
||||
:type key: bytes
|
||||
:param salt: a initialization salt at most
|
||||
:py:attr:`.SALT_SIZE` long; it will be zero-padded
|
||||
if needed
|
||||
:type salt: bytes
|
||||
:param person: a personalization string at most
|
||||
:py:attr:`.PERSONAL_SIZE` long; it will be zero-padded
|
||||
if needed
|
||||
:type person: bytes
|
||||
"""
|
||||
|
||||
self._state = _b2b_init(
|
||||
key=key, salt=salt, person=person, digest_size=digest_size
|
||||
)
|
||||
self._digest_size = digest_size
|
||||
|
||||
if data:
|
||||
self.update(data)
|
||||
|
||||
@property
|
||||
def digest_size(self) -> int:
|
||||
return self._digest_size
|
||||
|
||||
@property
|
||||
def block_size(self) -> int:
|
||||
return 128
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return "blake2b"
|
||||
|
||||
def update(self, data: bytes) -> None:
|
||||
_b2b_update(self._state, data)
|
||||
|
||||
def digest(self) -> bytes:
|
||||
_st = self._state.copy()
|
||||
return _b2b_final(_st)
|
||||
|
||||
def hexdigest(self) -> str:
|
||||
return bytes_as_string(binascii.hexlify(self.digest()))
|
||||
|
||||
def copy(self) -> "blake2b":
|
||||
_cp = type(self)(digest_size=self.digest_size)
|
||||
_st = self._state.copy()
|
||||
_cp._state = _st
|
||||
return _cp
|
||||
|
||||
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 scrypt(
|
||||
password: bytes,
|
||||
salt: bytes = b"",
|
||||
n: int = 2 ** 20,
|
||||
r: int = 8,
|
||||
p: int = 1,
|
||||
maxmem: int = 2 ** 25,
|
||||
dklen: int = 64,
|
||||
) -> bytes:
|
||||
"""
|
||||
Derive a cryptographic key using the scrypt KDF.
|
||||
|
||||
:raises nacl.exceptions.UnavailableError: If called when using a
|
||||
minimal build of libsodium.
|
||||
|
||||
Implements the same signature as the ``hashlib.scrypt`` implemented
|
||||
in cpython version 3.6
|
||||
"""
|
||||
return nacl.bindings.crypto_pwhash_scryptsalsa208sha256_ll(
|
||||
password, salt, n, r, p, maxmem=maxmem, dklen=dklen
|
||||
)
|
423
venv/lib/python3.11/site-packages/nacl/public.py
Normal file
423
venv/lib/python3.11/site-packages/nacl/public.py
Normal file
@ -0,0 +1,423 @@
|
||||
# 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 ClassVar, Generic, Optional, Type, TypeVar
|
||||
|
||||
import nacl.bindings
|
||||
from nacl import encoding
|
||||
from nacl import exceptions as exc
|
||||
from nacl.encoding import Encoder
|
||||
from nacl.utils import EncryptedMessage, StringFixer, random
|
||||
|
||||
|
||||
class PublicKey(encoding.Encodable, StringFixer):
|
||||
"""
|
||||
The public key counterpart to an Curve25519 :class:`nacl.public.PrivateKey`
|
||||
for encrypting messages.
|
||||
|
||||
:param public_key: [:class:`bytes`] Encoded Curve25519 public key
|
||||
:param encoder: A class that is able to decode the `public_key`
|
||||
|
||||
:cvar SIZE: The size that the public key is required to be
|
||||
"""
|
||||
|
||||
SIZE: ClassVar[int] = nacl.bindings.crypto_box_PUBLICKEYBYTES
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
public_key: bytes,
|
||||
encoder: encoding.Encoder = encoding.RawEncoder,
|
||||
):
|
||||
self._public_key = encoder.decode(public_key)
|
||||
if not isinstance(self._public_key, bytes):
|
||||
raise exc.TypeError("PublicKey must be created from 32 bytes")
|
||||
|
||||
if len(self._public_key) != self.SIZE:
|
||||
raise exc.ValueError(
|
||||
"The public key must be exactly {} bytes long".format(
|
||||
self.SIZE
|
||||
)
|
||||
)
|
||||
|
||||
def __bytes__(self) -> bytes:
|
||||
return self._public_key
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return hash(bytes(self))
|
||||
|
||||
def __eq__(self, other: object) -> bool:
|
||||
if not isinstance(other, self.__class__):
|
||||
return False
|
||||
return nacl.bindings.sodium_memcmp(bytes(self), bytes(other))
|
||||
|
||||
def __ne__(self, other: object) -> bool:
|
||||
return not (self == other)
|
||||
|
||||
|
||||
class PrivateKey(encoding.Encodable, StringFixer):
|
||||
"""
|
||||
Private key for decrypting messages using the Curve25519 algorithm.
|
||||
|
||||
.. warning:: This **must** be protected and remain secret. Anyone who
|
||||
knows the value of your :class:`~nacl.public.PrivateKey` can decrypt
|
||||
any message encrypted by the corresponding
|
||||
:class:`~nacl.public.PublicKey`
|
||||
|
||||
:param private_key: The private key used to decrypt messages
|
||||
:param encoder: The encoder class used to decode the given keys
|
||||
|
||||
:cvar SIZE: The size that the private key is required to be
|
||||
:cvar SEED_SIZE: The size that the seed used to generate the
|
||||
private key is required to be
|
||||
"""
|
||||
|
||||
SIZE: ClassVar[int] = nacl.bindings.crypto_box_SECRETKEYBYTES
|
||||
SEED_SIZE: ClassVar[int] = nacl.bindings.crypto_box_SEEDBYTES
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
private_key: bytes,
|
||||
encoder: encoding.Encoder = encoding.RawEncoder,
|
||||
):
|
||||
# Decode the secret_key
|
||||
private_key = encoder.decode(private_key)
|
||||
# verify the given secret key type and size are correct
|
||||
if not (
|
||||
isinstance(private_key, bytes) and len(private_key) == self.SIZE
|
||||
):
|
||||
raise exc.TypeError(
|
||||
(
|
||||
"PrivateKey must be created from a {} "
|
||||
"bytes long raw secret key"
|
||||
).format(self.SIZE)
|
||||
)
|
||||
|
||||
raw_public_key = nacl.bindings.crypto_scalarmult_base(private_key)
|
||||
|
||||
self._private_key = private_key
|
||||
self.public_key = PublicKey(raw_public_key)
|
||||
|
||||
@classmethod
|
||||
def from_seed(
|
||||
cls,
|
||||
seed: bytes,
|
||||
encoder: encoding.Encoder = encoding.RawEncoder,
|
||||
) -> "PrivateKey":
|
||||
"""
|
||||
Generate a PrivateKey using a deterministic construction
|
||||
starting from a caller-provided 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: The seed used to generate the private key
|
||||
:rtype: :class:`~nacl.public.PrivateKey`
|
||||
"""
|
||||
# decode the seed
|
||||
seed = encoder.decode(seed)
|
||||
# Verify the given seed type and size are correct
|
||||
if not (isinstance(seed, bytes) and len(seed) == cls.SEED_SIZE):
|
||||
raise exc.TypeError(
|
||||
(
|
||||
"PrivateKey seed must be a {} bytes long "
|
||||
"binary sequence"
|
||||
).format(cls.SEED_SIZE)
|
||||
)
|
||||
# generate a raw keypair from the given seed
|
||||
raw_pk, raw_sk = nacl.bindings.crypto_box_seed_keypair(seed)
|
||||
# construct a instance from the raw secret key
|
||||
return cls(raw_sk)
|
||||
|
||||
def __bytes__(self) -> bytes:
|
||||
return self._private_key
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return hash((type(self), bytes(self.public_key)))
|
||||
|
||||
def __eq__(self, other: object) -> bool:
|
||||
if not isinstance(other, self.__class__):
|
||||
return False
|
||||
return self.public_key == other.public_key
|
||||
|
||||
def __ne__(self, other: object) -> bool:
|
||||
return not (self == other)
|
||||
|
||||
@classmethod
|
||||
def generate(cls) -> "PrivateKey":
|
||||
"""
|
||||
Generates a random :class:`~nacl.public.PrivateKey` object
|
||||
|
||||
:rtype: :class:`~nacl.public.PrivateKey`
|
||||
"""
|
||||
return cls(random(PrivateKey.SIZE), encoder=encoding.RawEncoder)
|
||||
|
||||
|
||||
_Box = TypeVar("_Box", bound="Box")
|
||||
|
||||
|
||||
class Box(encoding.Encodable, StringFixer):
|
||||
"""
|
||||
The Box class boxes and unboxes messages between a pair of keys
|
||||
|
||||
The ciphertexts generated by :class:`~nacl.public.Box` include a 16
|
||||
byte authenticator which is checked as part of the decryption. An invalid
|
||||
authenticator will cause the decrypt function to raise an exception. The
|
||||
authenticator is not a signature. Once you've decrypted the message you've
|
||||
demonstrated the ability to create arbitrary valid message, so messages you
|
||||
send are repudiable. For non-repudiable messages, sign them after
|
||||
encryption.
|
||||
|
||||
:param private_key: :class:`~nacl.public.PrivateKey` used to encrypt and
|
||||
decrypt messages
|
||||
:param public_key: :class:`~nacl.public.PublicKey` used to encrypt and
|
||||
decrypt messages
|
||||
|
||||
:cvar NONCE_SIZE: The size that the nonce is required to be.
|
||||
"""
|
||||
|
||||
NONCE_SIZE: ClassVar[int] = nacl.bindings.crypto_box_NONCEBYTES
|
||||
_shared_key: bytes
|
||||
|
||||
def __init__(self, private_key: PrivateKey, public_key: PublicKey):
|
||||
if not isinstance(private_key, PrivateKey) or not isinstance(
|
||||
public_key, PublicKey
|
||||
):
|
||||
raise exc.TypeError(
|
||||
"Box must be created from a PrivateKey and a PublicKey"
|
||||
)
|
||||
self._shared_key = nacl.bindings.crypto_box_beforenm(
|
||||
public_key.encode(encoder=encoding.RawEncoder),
|
||||
private_key.encode(encoder=encoding.RawEncoder),
|
||||
)
|
||||
|
||||
def __bytes__(self) -> bytes:
|
||||
return self._shared_key
|
||||
|
||||
@classmethod
|
||||
def decode(
|
||||
cls: Type[_Box], encoded: bytes, encoder: Encoder = encoding.RawEncoder
|
||||
) -> _Box:
|
||||
"""
|
||||
Alternative constructor. Creates a Box from an existing Box's shared key.
|
||||
"""
|
||||
# Create an empty box
|
||||
box: _Box = cls.__new__(cls)
|
||||
|
||||
# Assign our decoded value to the shared key of the box
|
||||
box._shared_key = encoder.decode(encoded)
|
||||
|
||||
return box
|
||||
|
||||
def encrypt(
|
||||
self,
|
||||
plaintext: bytes,
|
||||
nonce: Optional[bytes] = None,
|
||||
encoder: encoding.Encoder = encoding.RawEncoder,
|
||||
) -> EncryptedMessage:
|
||||
"""
|
||||
Encrypts the plaintext message using the given `nonce` (or generates
|
||||
one randomly if omitted) and returns the ciphertext encoded with the
|
||||
encoder.
|
||||
|
||||
.. warning:: It is **VITALLY** important that the nonce is a nonce,
|
||||
i.e. it is a number used only once for any given key. If you fail
|
||||
to do this, you compromise the privacy of the messages encrypted.
|
||||
|
||||
:param plaintext: [:class:`bytes`] The plaintext message to encrypt
|
||||
:param nonce: [:class:`bytes`] The nonce to use in the encryption
|
||||
:param encoder: The encoder to use to encode the ciphertext
|
||||
:rtype: [:class:`nacl.utils.EncryptedMessage`]
|
||||
"""
|
||||
if nonce is None:
|
||||
nonce = random(self.NONCE_SIZE)
|
||||
|
||||
if len(nonce) != self.NONCE_SIZE:
|
||||
raise exc.ValueError(
|
||||
"The nonce must be exactly %s bytes long" % self.NONCE_SIZE
|
||||
)
|
||||
|
||||
ciphertext = nacl.bindings.crypto_box_afternm(
|
||||
plaintext,
|
||||
nonce,
|
||||
self._shared_key,
|
||||
)
|
||||
|
||||
encoded_nonce = encoder.encode(nonce)
|
||||
encoded_ciphertext = encoder.encode(ciphertext)
|
||||
|
||||
return EncryptedMessage._from_parts(
|
||||
encoded_nonce,
|
||||
encoded_ciphertext,
|
||||
encoder.encode(nonce + ciphertext),
|
||||
)
|
||||
|
||||
def decrypt(
|
||||
self,
|
||||
ciphertext: bytes,
|
||||
nonce: Optional[bytes] = None,
|
||||
encoder: encoding.Encoder = encoding.RawEncoder,
|
||||
) -> bytes:
|
||||
"""
|
||||
Decrypts the ciphertext using the `nonce` (explicitly, when passed as a
|
||||
parameter or implicitly, when omitted, as part of the ciphertext) and
|
||||
returns the plaintext message.
|
||||
|
||||
:param ciphertext: [:class:`bytes`] The encrypted message to decrypt
|
||||
:param nonce: [:class:`bytes`] The nonce used when encrypting the
|
||||
ciphertext
|
||||
:param encoder: The encoder used to decode the ciphertext.
|
||||
:rtype: [:class:`bytes`]
|
||||
"""
|
||||
# Decode our ciphertext
|
||||
ciphertext = encoder.decode(ciphertext)
|
||||
|
||||
if nonce is None:
|
||||
# If we were given the nonce and ciphertext combined, split them.
|
||||
nonce = ciphertext[: self.NONCE_SIZE]
|
||||
ciphertext = ciphertext[self.NONCE_SIZE :]
|
||||
|
||||
if len(nonce) != self.NONCE_SIZE:
|
||||
raise exc.ValueError(
|
||||
"The nonce must be exactly %s bytes long" % self.NONCE_SIZE
|
||||
)
|
||||
|
||||
plaintext = nacl.bindings.crypto_box_open_afternm(
|
||||
ciphertext,
|
||||
nonce,
|
||||
self._shared_key,
|
||||
)
|
||||
|
||||
return plaintext
|
||||
|
||||
def shared_key(self) -> bytes:
|
||||
"""
|
||||
Returns the Curve25519 shared secret, that can then be used as a key in
|
||||
other symmetric ciphers.
|
||||
|
||||
.. warning:: It is **VITALLY** important that you use a nonce with your
|
||||
symmetric cipher. If you fail to do this, you compromise the
|
||||
privacy of the messages encrypted. Ensure that the key length of
|
||||
your cipher is 32 bytes.
|
||||
:rtype: [:class:`bytes`]
|
||||
"""
|
||||
|
||||
return self._shared_key
|
||||
|
||||
|
||||
_Key = TypeVar("_Key", PublicKey, PrivateKey)
|
||||
|
||||
|
||||
class SealedBox(Generic[_Key], encoding.Encodable, StringFixer):
|
||||
"""
|
||||
The SealedBox class boxes and unboxes messages addressed to
|
||||
a specified key-pair by using ephemeral sender's keypairs,
|
||||
whose private part will be discarded just after encrypting
|
||||
a single plaintext message.
|
||||
|
||||
The ciphertexts generated by :class:`~nacl.public.SecretBox` include
|
||||
the public part of the ephemeral key before the :class:`~nacl.public.Box`
|
||||
ciphertext.
|
||||
|
||||
:param recipient_key: a :class:`~nacl.public.PublicKey` used to encrypt
|
||||
messages and derive nonces, or a :class:`~nacl.public.PrivateKey` used
|
||||
to decrypt messages.
|
||||
|
||||
.. versionadded:: 1.2
|
||||
"""
|
||||
|
||||
_public_key: bytes
|
||||
_private_key: Optional[bytes]
|
||||
|
||||
def __init__(self, recipient_key: _Key):
|
||||
if isinstance(recipient_key, PublicKey):
|
||||
self._public_key = recipient_key.encode(
|
||||
encoder=encoding.RawEncoder
|
||||
)
|
||||
self._private_key = None
|
||||
elif isinstance(recipient_key, PrivateKey):
|
||||
self._private_key = recipient_key.encode(
|
||||
encoder=encoding.RawEncoder
|
||||
)
|
||||
self._public_key = recipient_key.public_key.encode(
|
||||
encoder=encoding.RawEncoder
|
||||
)
|
||||
else:
|
||||
raise exc.TypeError(
|
||||
"SealedBox must be created from a PublicKey or a PrivateKey"
|
||||
)
|
||||
|
||||
def __bytes__(self) -> bytes:
|
||||
return self._public_key
|
||||
|
||||
def encrypt(
|
||||
self,
|
||||
plaintext: bytes,
|
||||
encoder: encoding.Encoder = encoding.RawEncoder,
|
||||
) -> bytes:
|
||||
"""
|
||||
Encrypts the plaintext message using a random-generated ephemeral
|
||||
keypair and returns a "composed ciphertext", containing both
|
||||
the public part of the keypair and the ciphertext proper,
|
||||
encoded with the encoder.
|
||||
|
||||
The private part of the ephemeral key-pair will be scrubbed before
|
||||
returning the ciphertext, therefore, the sender will not be able to
|
||||
decrypt the generated ciphertext.
|
||||
|
||||
:param plaintext: [:class:`bytes`] The plaintext message to encrypt
|
||||
:param encoder: The encoder to use to encode the ciphertext
|
||||
:return bytes: encoded ciphertext
|
||||
"""
|
||||
|
||||
ciphertext = nacl.bindings.crypto_box_seal(plaintext, self._public_key)
|
||||
|
||||
encoded_ciphertext = encoder.encode(ciphertext)
|
||||
|
||||
return encoded_ciphertext
|
||||
|
||||
def decrypt(
|
||||
self: "SealedBox[PrivateKey]",
|
||||
ciphertext: bytes,
|
||||
encoder: encoding.Encoder = encoding.RawEncoder,
|
||||
) -> bytes:
|
||||
"""
|
||||
Decrypts the ciphertext using the ephemeral public key enclosed
|
||||
in the ciphertext and the SealedBox private key, returning
|
||||
the plaintext message.
|
||||
|
||||
:param ciphertext: [:class:`bytes`] The encrypted message to decrypt
|
||||
:param encoder: The encoder used to decode the ciphertext.
|
||||
:return bytes: The original plaintext
|
||||
:raises TypeError: if this SealedBox was created with a
|
||||
:class:`~nacl.public.PublicKey` rather than a
|
||||
:class:`~nacl.public.PrivateKey`.
|
||||
"""
|
||||
# Decode our ciphertext
|
||||
ciphertext = encoder.decode(ciphertext)
|
||||
|
||||
if self._private_key is None:
|
||||
raise TypeError(
|
||||
"SealedBoxes created with a public key cannot decrypt"
|
||||
)
|
||||
plaintext = nacl.bindings.crypto_box_seal_open(
|
||||
ciphertext,
|
||||
self._public_key,
|
||||
self._private_key,
|
||||
)
|
||||
|
||||
return plaintext
|
75
venv/lib/python3.11/site-packages/nacl/pwhash/__init__.py
Normal file
75
venv/lib/python3.11/site-packages/nacl/pwhash/__init__.py
Normal file
@ -0,0 +1,75 @@
|
||||
# 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 nacl.exceptions import CryptPrefixError
|
||||
|
||||
from . import _argon2, argon2i, argon2id, scrypt
|
||||
|
||||
STRPREFIX = argon2id.STRPREFIX
|
||||
|
||||
PWHASH_SIZE = argon2id.PWHASH_SIZE
|
||||
|
||||
assert _argon2.ALG_ARGON2_DEFAULT == _argon2.ALG_ARGON2ID13
|
||||
# since version 1.0.15 of libsodium
|
||||
|
||||
PASSWD_MIN = argon2id.PASSWD_MIN
|
||||
PASSWD_MAX = argon2id.PASSWD_MAX
|
||||
MEMLIMIT_MAX = argon2id.MEMLIMIT_MAX
|
||||
MEMLIMIT_MIN = argon2id.MEMLIMIT_MIN
|
||||
OPSLIMIT_MAX = argon2id.OPSLIMIT_MAX
|
||||
OPSLIMIT_MIN = argon2id.OPSLIMIT_MIN
|
||||
OPSLIMIT_INTERACTIVE = argon2id.OPSLIMIT_INTERACTIVE
|
||||
MEMLIMIT_INTERACTIVE = argon2id.MEMLIMIT_INTERACTIVE
|
||||
OPSLIMIT_MODERATE = argon2id.OPSLIMIT_MODERATE
|
||||
MEMLIMIT_MODERATE = argon2id.MEMLIMIT_MODERATE
|
||||
OPSLIMIT_SENSITIVE = argon2id.OPSLIMIT_SENSITIVE
|
||||
MEMLIMIT_SENSITIVE = argon2id.MEMLIMIT_SENSITIVE
|
||||
|
||||
str = argon2id.str
|
||||
|
||||
assert argon2i.ALG != argon2id.ALG
|
||||
|
||||
SCRYPT_SALTBYTES = scrypt.SALTBYTES
|
||||
SCRYPT_PWHASH_SIZE = scrypt.PWHASH_SIZE
|
||||
SCRYPT_OPSLIMIT_INTERACTIVE = scrypt.OPSLIMIT_INTERACTIVE
|
||||
SCRYPT_MEMLIMIT_INTERACTIVE = scrypt.MEMLIMIT_INTERACTIVE
|
||||
SCRYPT_OPSLIMIT_SENSITIVE = scrypt.OPSLIMIT_SENSITIVE
|
||||
SCRYPT_MEMLIMIT_SENSITIVE = scrypt.MEMLIMIT_SENSITIVE
|
||||
|
||||
|
||||
kdf_scryptsalsa208sha256 = scrypt.kdf
|
||||
scryptsalsa208sha256_str = scrypt.str
|
||||
verify_scryptsalsa208sha256 = scrypt.verify
|
||||
|
||||
|
||||
def verify(password_hash: bytes, password: bytes) -> bool:
|
||||
"""
|
||||
Takes a modular crypt encoded stored password hash derived using one
|
||||
of the algorithms supported by `libsodium` and checks if the user provided
|
||||
password will hash to the same string when using the parameters saved
|
||||
in the stored hash
|
||||
"""
|
||||
if password_hash.startswith(argon2id.STRPREFIX):
|
||||
return argon2id.verify(password_hash, password)
|
||||
elif password_hash.startswith(argon2i.STRPREFIX):
|
||||
return argon2id.verify(password_hash, password)
|
||||
elif scrypt.AVAILABLE and password_hash.startswith(scrypt.STRPREFIX):
|
||||
return scrypt.verify(password_hash, password)
|
||||
else:
|
||||
raise (
|
||||
CryptPrefixError(
|
||||
"given password_hash is not in a supported format"
|
||||
)
|
||||
)
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
49
venv/lib/python3.11/site-packages/nacl/pwhash/_argon2.py
Normal file
49
venv/lib/python3.11/site-packages/nacl/pwhash/_argon2.py
Normal file
@ -0,0 +1,49 @@
|
||||
# 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 nacl.bindings
|
||||
|
||||
_argon2_strbytes_plus_one = nacl.bindings.crypto_pwhash_STRBYTES
|
||||
|
||||
PWHASH_SIZE = _argon2_strbytes_plus_one - 1
|
||||
SALTBYTES = nacl.bindings.crypto_pwhash_SALTBYTES
|
||||
|
||||
PASSWD_MIN = nacl.bindings.crypto_pwhash_PASSWD_MIN
|
||||
PASSWD_MAX = nacl.bindings.crypto_pwhash_PASSWD_MAX
|
||||
|
||||
PWHASH_SIZE = _argon2_strbytes_plus_one - 1
|
||||
|
||||
BYTES_MAX = nacl.bindings.crypto_pwhash_BYTES_MAX
|
||||
BYTES_MIN = nacl.bindings.crypto_pwhash_BYTES_MIN
|
||||
|
||||
ALG_ARGON2I13 = nacl.bindings.crypto_pwhash_ALG_ARGON2I13
|
||||
ALG_ARGON2ID13 = nacl.bindings.crypto_pwhash_ALG_ARGON2ID13
|
||||
ALG_ARGON2_DEFAULT = nacl.bindings.crypto_pwhash_ALG_DEFAULT
|
||||
|
||||
|
||||
def verify(password_hash: bytes, password: bytes) -> bool:
|
||||
"""
|
||||
Takes a modular crypt encoded argon2i or argon2id stored password hash
|
||||
and checks if the user provided password will hash to the same string
|
||||
when using the stored parameters
|
||||
|
||||
:param password_hash: password hash serialized in modular crypt() format
|
||||
:type password_hash: bytes
|
||||
:param password: user provided password
|
||||
:type password: bytes
|
||||
:rtype: boolean
|
||||
|
||||
.. versionadded:: 1.2
|
||||
"""
|
||||
return nacl.bindings.crypto_pwhash_str_verify(password_hash, password)
|
132
venv/lib/python3.11/site-packages/nacl/pwhash/argon2i.py
Normal file
132
venv/lib/python3.11/site-packages/nacl/pwhash/argon2i.py
Normal file
@ -0,0 +1,132 @@
|
||||
# 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 nacl.bindings
|
||||
import nacl.encoding
|
||||
|
||||
from . import _argon2
|
||||
|
||||
ALG = _argon2.ALG_ARGON2I13
|
||||
STRPREFIX = nacl.bindings.crypto_pwhash_argon2i_STRPREFIX
|
||||
|
||||
SALTBYTES = _argon2.SALTBYTES
|
||||
|
||||
PASSWD_MIN = _argon2.PASSWD_MIN
|
||||
PASSWD_MAX = _argon2.PASSWD_MAX
|
||||
|
||||
PWHASH_SIZE = _argon2.PWHASH_SIZE
|
||||
|
||||
BYTES_MIN = _argon2.BYTES_MIN
|
||||
BYTES_MAX = _argon2.BYTES_MAX
|
||||
|
||||
verify = _argon2.verify
|
||||
|
||||
MEMLIMIT_MAX = nacl.bindings.crypto_pwhash_argon2i_MEMLIMIT_MAX
|
||||
MEMLIMIT_MIN = nacl.bindings.crypto_pwhash_argon2i_MEMLIMIT_MIN
|
||||
OPSLIMIT_MAX = nacl.bindings.crypto_pwhash_argon2i_OPSLIMIT_MAX
|
||||
OPSLIMIT_MIN = nacl.bindings.crypto_pwhash_argon2i_OPSLIMIT_MIN
|
||||
|
||||
OPSLIMIT_INTERACTIVE = nacl.bindings.crypto_pwhash_argon2i_OPSLIMIT_INTERACTIVE
|
||||
MEMLIMIT_INTERACTIVE = nacl.bindings.crypto_pwhash_argon2i_MEMLIMIT_INTERACTIVE
|
||||
OPSLIMIT_SENSITIVE = nacl.bindings.crypto_pwhash_argon2i_OPSLIMIT_SENSITIVE
|
||||
MEMLIMIT_SENSITIVE = nacl.bindings.crypto_pwhash_argon2i_MEMLIMIT_SENSITIVE
|
||||
|
||||
OPSLIMIT_MODERATE = nacl.bindings.crypto_pwhash_argon2i_OPSLIMIT_MODERATE
|
||||
MEMLIMIT_MODERATE = nacl.bindings.crypto_pwhash_argon2i_MEMLIMIT_MODERATE
|
||||
|
||||
|
||||
def kdf(
|
||||
size: int,
|
||||
password: bytes,
|
||||
salt: bytes,
|
||||
opslimit: int = OPSLIMIT_SENSITIVE,
|
||||
memlimit: int = MEMLIMIT_SENSITIVE,
|
||||
encoder: nacl.encoding.Encoder = nacl.encoding.RawEncoder,
|
||||
) -> bytes:
|
||||
"""
|
||||
Derive a ``size`` bytes long key from a caller-supplied
|
||||
``password`` and ``salt`` pair using the argon2i
|
||||
memory-hard construct.
|
||||
|
||||
the enclosing module provides the constants
|
||||
|
||||
- :py:const:`.OPSLIMIT_INTERACTIVE`
|
||||
- :py:const:`.MEMLIMIT_INTERACTIVE`
|
||||
- :py:const:`.OPSLIMIT_MODERATE`
|
||||
- :py:const:`.MEMLIMIT_MODERATE`
|
||||
- :py:const:`.OPSLIMIT_SENSITIVE`
|
||||
- :py:const:`.MEMLIMIT_SENSITIVE`
|
||||
|
||||
as a guidance for correct settings.
|
||||
|
||||
:param size: derived key size, must be between
|
||||
:py:const:`.BYTES_MIN` and
|
||||
:py:const:`.BYTES_MAX`
|
||||
:type size: int
|
||||
:param password: password used to seed the key derivation procedure;
|
||||
it length must be between
|
||||
:py:const:`.PASSWD_MIN` and
|
||||
:py:const:`.PASSWD_MAX`
|
||||
:type password: bytes
|
||||
:param salt: **RANDOM** salt used in the key derivation procedure;
|
||||
its length must be exactly :py:const:`.SALTBYTES`
|
||||
:type salt: bytes
|
||||
:param opslimit: the time component (operation count)
|
||||
of the key derivation procedure's computational cost;
|
||||
it must be between
|
||||
:py:const:`.OPSLIMIT_MIN` and
|
||||
:py:const:`.OPSLIMIT_MAX`
|
||||
:type opslimit: int
|
||||
:param memlimit: the memory occupation component
|
||||
of the key derivation procedure's computational cost;
|
||||
it must be between
|
||||
:py:const:`.MEMLIMIT_MIN` and
|
||||
:py:const:`.MEMLIMIT_MAX`
|
||||
:type memlimit: int
|
||||
:rtype: bytes
|
||||
|
||||
.. versionadded:: 1.2
|
||||
"""
|
||||
|
||||
return encoder.encode(
|
||||
nacl.bindings.crypto_pwhash_alg(
|
||||
size, password, salt, opslimit, memlimit, ALG
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def str(
|
||||
password: bytes,
|
||||
opslimit: int = OPSLIMIT_INTERACTIVE,
|
||||
memlimit: int = MEMLIMIT_INTERACTIVE,
|
||||
) -> bytes:
|
||||
"""
|
||||
Hashes a password with a random salt, using the memory-hard
|
||||
argon2i construct and returning an ascii string that has all
|
||||
the needed info to check against a future password
|
||||
|
||||
|
||||
The default settings for opslimit and memlimit are those deemed
|
||||
correct for the interactive user login case.
|
||||
|
||||
:param bytes password:
|
||||
:param int opslimit:
|
||||
:param int memlimit:
|
||||
:rtype: bytes
|
||||
|
||||
.. versionadded:: 1.2
|
||||
"""
|
||||
return nacl.bindings.crypto_pwhash_str_alg(
|
||||
password, opslimit, memlimit, ALG
|
||||
)
|
135
venv/lib/python3.11/site-packages/nacl/pwhash/argon2id.py
Normal file
135
venv/lib/python3.11/site-packages/nacl/pwhash/argon2id.py
Normal file
@ -0,0 +1,135 @@
|
||||
# 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 nacl.bindings
|
||||
import nacl.encoding
|
||||
|
||||
from . import _argon2
|
||||
|
||||
ALG = _argon2.ALG_ARGON2ID13
|
||||
STRPREFIX = nacl.bindings.crypto_pwhash_argon2id_STRPREFIX
|
||||
|
||||
SALTBYTES = _argon2.SALTBYTES
|
||||
|
||||
PASSWD_MIN = _argon2.PASSWD_MIN
|
||||
PASSWD_MAX = _argon2.PASSWD_MAX
|
||||
|
||||
PWHASH_SIZE = _argon2.PWHASH_SIZE
|
||||
|
||||
BYTES_MIN = _argon2.BYTES_MIN
|
||||
BYTES_MAX = _argon2.BYTES_MAX
|
||||
|
||||
verify = _argon2.verify
|
||||
|
||||
MEMLIMIT_MIN = nacl.bindings.crypto_pwhash_argon2id_MEMLIMIT_MIN
|
||||
MEMLIMIT_MAX = nacl.bindings.crypto_pwhash_argon2id_MEMLIMIT_MAX
|
||||
OPSLIMIT_MIN = nacl.bindings.crypto_pwhash_argon2id_OPSLIMIT_MIN
|
||||
OPSLIMIT_MAX = nacl.bindings.crypto_pwhash_argon2id_OPSLIMIT_MAX
|
||||
|
||||
OPSLIMIT_INTERACTIVE = (
|
||||
nacl.bindings.crypto_pwhash_argon2id_OPSLIMIT_INTERACTIVE
|
||||
)
|
||||
MEMLIMIT_INTERACTIVE = (
|
||||
nacl.bindings.crypto_pwhash_argon2id_MEMLIMIT_INTERACTIVE
|
||||
)
|
||||
OPSLIMIT_SENSITIVE = nacl.bindings.crypto_pwhash_argon2id_OPSLIMIT_SENSITIVE
|
||||
MEMLIMIT_SENSITIVE = nacl.bindings.crypto_pwhash_argon2id_MEMLIMIT_SENSITIVE
|
||||
|
||||
OPSLIMIT_MODERATE = nacl.bindings.crypto_pwhash_argon2id_OPSLIMIT_MODERATE
|
||||
MEMLIMIT_MODERATE = nacl.bindings.crypto_pwhash_argon2id_MEMLIMIT_MODERATE
|
||||
|
||||
|
||||
def kdf(
|
||||
size: int,
|
||||
password: bytes,
|
||||
salt: bytes,
|
||||
opslimit: int = OPSLIMIT_SENSITIVE,
|
||||
memlimit: int = MEMLIMIT_SENSITIVE,
|
||||
encoder: nacl.encoding.Encoder = nacl.encoding.RawEncoder,
|
||||
) -> bytes:
|
||||
"""
|
||||
Derive a ``size`` bytes long key from a caller-supplied
|
||||
``password`` and ``salt`` pair using the argon2i
|
||||
memory-hard construct.
|
||||
|
||||
the enclosing module provides the constants
|
||||
|
||||
- :py:const:`.OPSLIMIT_INTERACTIVE`
|
||||
- :py:const:`.MEMLIMIT_INTERACTIVE`
|
||||
- :py:const:`.OPSLIMIT_MODERATE`
|
||||
- :py:const:`.MEMLIMIT_MODERATE`
|
||||
- :py:const:`.OPSLIMIT_SENSITIVE`
|
||||
- :py:const:`.MEMLIMIT_SENSITIVE`
|
||||
|
||||
as a guidance for correct settings.
|
||||
|
||||
:param size: derived key size, must be between
|
||||
:py:const:`.BYTES_MIN` and
|
||||
:py:const:`.BYTES_MAX`
|
||||
:type size: int
|
||||
:param password: password used to seed the key derivation procedure;
|
||||
it length must be between
|
||||
:py:const:`.PASSWD_MIN` and
|
||||
:py:const:`.PASSWD_MAX`
|
||||
:type password: bytes
|
||||
:param salt: **RANDOM** salt used in the key derivation procedure;
|
||||
its length must be exactly :py:const:`.SALTBYTES`
|
||||
:type salt: bytes
|
||||
:param opslimit: the time component (operation count)
|
||||
of the key derivation procedure's computational cost;
|
||||
it must be between
|
||||
:py:const:`.OPSLIMIT_MIN` and
|
||||
:py:const:`.OPSLIMIT_MAX`
|
||||
:type opslimit: int
|
||||
:param memlimit: the memory occupation component
|
||||
of the key derivation procedure's computational cost;
|
||||
it must be between
|
||||
:py:const:`.MEMLIMIT_MIN` and
|
||||
:py:const:`.MEMLIMIT_MAX`
|
||||
:type memlimit: int
|
||||
:rtype: bytes
|
||||
|
||||
.. versionadded:: 1.2
|
||||
"""
|
||||
|
||||
return encoder.encode(
|
||||
nacl.bindings.crypto_pwhash_alg(
|
||||
size, password, salt, opslimit, memlimit, ALG
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def str(
|
||||
password: bytes,
|
||||
opslimit: int = OPSLIMIT_INTERACTIVE,
|
||||
memlimit: int = MEMLIMIT_INTERACTIVE,
|
||||
) -> bytes:
|
||||
"""
|
||||
Hashes a password with a random salt, using the memory-hard
|
||||
argon2id construct and returning an ascii string that has all
|
||||
the needed info to check against a future password
|
||||
|
||||
The default settings for opslimit and memlimit are those deemed
|
||||
correct for the interactive user login case.
|
||||
|
||||
:param bytes password:
|
||||
:param int opslimit:
|
||||
:param int memlimit:
|
||||
:rtype: bytes
|
||||
|
||||
.. versionadded:: 1.2
|
||||
"""
|
||||
return nacl.bindings.crypto_pwhash_str_alg(
|
||||
password, opslimit, memlimit, ALG
|
||||
)
|
211
venv/lib/python3.11/site-packages/nacl/pwhash/scrypt.py
Normal file
211
venv/lib/python3.11/site-packages/nacl/pwhash/scrypt.py
Normal file
@ -0,0 +1,211 @@
|
||||
# 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 cast
|
||||
|
||||
import nacl.bindings
|
||||
import nacl.encoding
|
||||
from nacl import exceptions as exc
|
||||
from nacl.exceptions import ensure
|
||||
|
||||
_strbytes_plus_one = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_STRBYTES
|
||||
|
||||
AVAILABLE = nacl.bindings.has_crypto_pwhash_scryptsalsa208sha256
|
||||
|
||||
STRPREFIX = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_STRPREFIX
|
||||
|
||||
SALTBYTES = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_SALTBYTES
|
||||
|
||||
PASSWD_MIN = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN
|
||||
PASSWD_MAX = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX
|
||||
|
||||
PWHASH_SIZE = _strbytes_plus_one - 1
|
||||
|
||||
BYTES_MIN = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_BYTES_MIN
|
||||
BYTES_MAX = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_BYTES_MAX
|
||||
|
||||
MEMLIMIT_MIN = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN
|
||||
MEMLIMIT_MAX = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX
|
||||
OPSLIMIT_MIN = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN
|
||||
OPSLIMIT_MAX = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX
|
||||
|
||||
OPSLIMIT_INTERACTIVE = (
|
||||
nacl.bindings.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE
|
||||
)
|
||||
MEMLIMIT_INTERACTIVE = (
|
||||
nacl.bindings.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE
|
||||
)
|
||||
OPSLIMIT_SENSITIVE = (
|
||||
nacl.bindings.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE
|
||||
)
|
||||
MEMLIMIT_SENSITIVE = (
|
||||
nacl.bindings.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE
|
||||
)
|
||||
|
||||
OPSLIMIT_MODERATE = 8 * OPSLIMIT_INTERACTIVE
|
||||
MEMLIMIT_MODERATE = 8 * MEMLIMIT_INTERACTIVE
|
||||
|
||||
|
||||
def kdf(
|
||||
size: int,
|
||||
password: bytes,
|
||||
salt: bytes,
|
||||
opslimit: int = OPSLIMIT_SENSITIVE,
|
||||
memlimit: int = MEMLIMIT_SENSITIVE,
|
||||
encoder: nacl.encoding.Encoder = nacl.encoding.RawEncoder,
|
||||
) -> bytes:
|
||||
"""
|
||||
Derive a ``size`` bytes long key from a caller-supplied
|
||||
``password`` and ``salt`` pair using the scryptsalsa208sha256
|
||||
memory-hard construct.
|
||||
|
||||
|
||||
the enclosing module provides the constants
|
||||
|
||||
- :py:const:`.OPSLIMIT_INTERACTIVE`
|
||||
- :py:const:`.MEMLIMIT_INTERACTIVE`
|
||||
- :py:const:`.OPSLIMIT_SENSITIVE`
|
||||
- :py:const:`.MEMLIMIT_SENSITIVE`
|
||||
- :py:const:`.OPSLIMIT_MODERATE`
|
||||
- :py:const:`.MEMLIMIT_MODERATE`
|
||||
|
||||
as a guidance for correct settings respectively for the
|
||||
interactive login and the long term key protecting sensitive data
|
||||
use cases.
|
||||
|
||||
:param size: derived key size, must be between
|
||||
:py:const:`.BYTES_MIN` and
|
||||
:py:const:`.BYTES_MAX`
|
||||
:type size: int
|
||||
:param password: password used to seed the key derivation procedure;
|
||||
it length must be between
|
||||
:py:const:`.PASSWD_MIN` and
|
||||
:py:const:`.PASSWD_MAX`
|
||||
:type password: bytes
|
||||
:param salt: **RANDOM** salt used in the key derivation procedure;
|
||||
its length must be exactly :py:const:`.SALTBYTES`
|
||||
:type salt: bytes
|
||||
:param opslimit: the time component (operation count)
|
||||
of the key derivation procedure's computational cost;
|
||||
it must be between
|
||||
:py:const:`.OPSLIMIT_MIN` and
|
||||
:py:const:`.OPSLIMIT_MAX`
|
||||
:type opslimit: int
|
||||
:param memlimit: the memory occupation component
|
||||
of the key derivation procedure's computational cost;
|
||||
it must be between
|
||||
:py:const:`.MEMLIMIT_MIN` and
|
||||
:py:const:`.MEMLIMIT_MAX`
|
||||
:type memlimit: int
|
||||
:rtype: bytes
|
||||
:raises nacl.exceptions.UnavailableError: If called when using a
|
||||
minimal build of libsodium.
|
||||
|
||||
.. versionadded:: 1.2
|
||||
"""
|
||||
ensure(
|
||||
AVAILABLE,
|
||||
"Not available in minimal build",
|
||||
raising=exc.UnavailableError,
|
||||
)
|
||||
|
||||
ensure(
|
||||
len(salt) == SALTBYTES,
|
||||
"The salt must be exactly %s, not %s bytes long"
|
||||
% (SALTBYTES, len(salt)),
|
||||
raising=exc.ValueError,
|
||||
)
|
||||
|
||||
n_log2, r, p = nacl.bindings.nacl_bindings_pick_scrypt_params(
|
||||
opslimit, memlimit
|
||||
)
|
||||
maxmem = memlimit + (2 ** 16)
|
||||
|
||||
return encoder.encode(
|
||||
nacl.bindings.crypto_pwhash_scryptsalsa208sha256_ll(
|
||||
password,
|
||||
salt,
|
||||
# Cast safety: n_log2 is a positive integer, and so 2 ** n_log2 is also
|
||||
# a positive integer. Mypy+typeshed can't deduce this, because there's no
|
||||
# way to for them to know that n_log2: int is positive.
|
||||
cast(int, 2 ** n_log2),
|
||||
r,
|
||||
p,
|
||||
maxmem=maxmem,
|
||||
dklen=size,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def str(
|
||||
password: bytes,
|
||||
opslimit: int = OPSLIMIT_INTERACTIVE,
|
||||
memlimit: int = MEMLIMIT_INTERACTIVE,
|
||||
) -> bytes:
|
||||
"""
|
||||
Hashes a password with a random salt, using the memory-hard
|
||||
scryptsalsa208sha256 construct and returning an ascii string
|
||||
that has all the needed info to check against a future password
|
||||
|
||||
The default settings for opslimit and memlimit are those deemed
|
||||
correct for the interactive user login case.
|
||||
|
||||
:param bytes password:
|
||||
:param int opslimit:
|
||||
:param int memlimit:
|
||||
:rtype: bytes
|
||||
:raises nacl.exceptions.UnavailableError: If called when using a
|
||||
minimal build of libsodium.
|
||||
|
||||
.. versionadded:: 1.2
|
||||
"""
|
||||
ensure(
|
||||
AVAILABLE,
|
||||
"Not available in minimal build",
|
||||
raising=exc.UnavailableError,
|
||||
)
|
||||
|
||||
return nacl.bindings.crypto_pwhash_scryptsalsa208sha256_str(
|
||||
password, opslimit, memlimit
|
||||
)
|
||||
|
||||
|
||||
def verify(password_hash: bytes, password: bytes) -> bool:
|
||||
"""
|
||||
Takes the output of scryptsalsa208sha256 and compares it against
|
||||
a user provided password to see if they are the same
|
||||
|
||||
:param password_hash: bytes
|
||||
:param password: bytes
|
||||
:rtype: boolean
|
||||
:raises nacl.exceptions.UnavailableError: If called when using a
|
||||
minimal build of libsodium.
|
||||
|
||||
.. versionadded:: 1.2
|
||||
"""
|
||||
ensure(
|
||||
AVAILABLE,
|
||||
"Not available in minimal build",
|
||||
raising=exc.UnavailableError,
|
||||
)
|
||||
|
||||
ensure(
|
||||
len(password_hash) == PWHASH_SIZE,
|
||||
"The password hash must be exactly %s bytes long"
|
||||
% nacl.bindings.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
|
||||
raising=exc.ValueError,
|
||||
)
|
||||
|
||||
return nacl.bindings.crypto_pwhash_scryptsalsa208sha256_str_verify(
|
||||
password_hash, password
|
||||
)
|
0
venv/lib/python3.11/site-packages/nacl/py.typed
Normal file
0
venv/lib/python3.11/site-packages/nacl/py.typed
Normal file
305
venv/lib/python3.11/site-packages/nacl/secret.py
Normal file
305
venv/lib/python3.11/site-packages/nacl/secret.py
Normal file
@ -0,0 +1,305 @@
|
||||
# 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 ClassVar, Optional
|
||||
|
||||
import nacl.bindings
|
||||
from nacl import encoding
|
||||
from nacl import exceptions as exc
|
||||
from nacl.utils import EncryptedMessage, StringFixer, random
|
||||
|
||||
|
||||
class SecretBox(encoding.Encodable, StringFixer):
|
||||
"""
|
||||
The SecretBox class encrypts and decrypts messages using the given secret
|
||||
key.
|
||||
|
||||
The ciphertexts generated by :class:`~nacl.secret.Secretbox` include a 16
|
||||
byte authenticator which is checked as part of the decryption. An invalid
|
||||
authenticator will cause the decrypt function to raise an exception. The
|
||||
authenticator is not a signature. Once you've decrypted the message you've
|
||||
demonstrated the ability to create arbitrary valid message, so messages you
|
||||
send are repudiable. For non-repudiable messages, sign them after
|
||||
encryption.
|
||||
|
||||
Encryption is done using `XSalsa20-Poly1305`_, and there are no practical
|
||||
limits on the number or size of messages (up to 2⁶⁴ messages, each up to 2⁶⁴
|
||||
bytes).
|
||||
|
||||
.. _XSalsa20-Poly1305: https://doc.libsodium.org/secret-key_cryptography/secretbox#algorithm-details
|
||||
|
||||
:param key: The secret key used to encrypt and decrypt messages
|
||||
:param encoder: The encoder class used to decode the given key
|
||||
|
||||
:cvar KEY_SIZE: The size that the key is required to be.
|
||||
:cvar NONCE_SIZE: The size that the nonce is required to be.
|
||||
:cvar MACBYTES: The size of the authentication MAC tag in bytes.
|
||||
:cvar MESSAGEBYTES_MAX: The maximum size of a message which can be
|
||||
safely encrypted with a single key/nonce
|
||||
pair.
|
||||
"""
|
||||
|
||||
KEY_SIZE: ClassVar[int] = nacl.bindings.crypto_secretbox_KEYBYTES
|
||||
NONCE_SIZE: ClassVar[int] = nacl.bindings.crypto_secretbox_NONCEBYTES
|
||||
MACBYTES: ClassVar[int] = nacl.bindings.crypto_secretbox_MACBYTES
|
||||
MESSAGEBYTES_MAX: ClassVar[
|
||||
int
|
||||
] = nacl.bindings.crypto_secretbox_MESSAGEBYTES_MAX
|
||||
|
||||
def __init__(
|
||||
self, key: bytes, encoder: encoding.Encoder = encoding.RawEncoder
|
||||
):
|
||||
key = encoder.decode(key)
|
||||
if not isinstance(key, bytes):
|
||||
raise exc.TypeError("SecretBox must be created from 32 bytes")
|
||||
|
||||
if len(key) != self.KEY_SIZE:
|
||||
raise exc.ValueError(
|
||||
"The key must be exactly %s bytes long" % self.KEY_SIZE,
|
||||
)
|
||||
|
||||
self._key = key
|
||||
|
||||
def __bytes__(self) -> bytes:
|
||||
return self._key
|
||||
|
||||
def encrypt(
|
||||
self,
|
||||
plaintext: bytes,
|
||||
nonce: Optional[bytes] = None,
|
||||
encoder: encoding.Encoder = encoding.RawEncoder,
|
||||
) -> EncryptedMessage:
|
||||
"""
|
||||
Encrypts the plaintext message using the given `nonce` (or generates
|
||||
one randomly if omitted) and returns the ciphertext encoded with the
|
||||
encoder.
|
||||
|
||||
.. warning:: It is **VITALLY** important that the nonce is a nonce,
|
||||
i.e. it is a number used only once for any given key. If you fail
|
||||
to do this, you compromise the privacy of the messages encrypted.
|
||||
Give your nonces a different prefix, or have one side use an odd
|
||||
counter and one an even counter. Just make sure they are different.
|
||||
|
||||
:param plaintext: [:class:`bytes`] The plaintext message to encrypt
|
||||
:param nonce: [:class:`bytes`] The nonce to use in the encryption
|
||||
:param encoder: The encoder to use to encode the ciphertext
|
||||
:rtype: [:class:`nacl.utils.EncryptedMessage`]
|
||||
"""
|
||||
if nonce is None:
|
||||
nonce = random(self.NONCE_SIZE)
|
||||
|
||||
if len(nonce) != self.NONCE_SIZE:
|
||||
raise exc.ValueError(
|
||||
"The nonce must be exactly %s bytes long" % self.NONCE_SIZE,
|
||||
)
|
||||
|
||||
ciphertext = nacl.bindings.crypto_secretbox(
|
||||
plaintext, nonce, self._key
|
||||
)
|
||||
|
||||
encoded_nonce = encoder.encode(nonce)
|
||||
encoded_ciphertext = encoder.encode(ciphertext)
|
||||
|
||||
return EncryptedMessage._from_parts(
|
||||
encoded_nonce,
|
||||
encoded_ciphertext,
|
||||
encoder.encode(nonce + ciphertext),
|
||||
)
|
||||
|
||||
def decrypt(
|
||||
self,
|
||||
ciphertext: bytes,
|
||||
nonce: Optional[bytes] = None,
|
||||
encoder: encoding.Encoder = encoding.RawEncoder,
|
||||
) -> bytes:
|
||||
"""
|
||||
Decrypts the ciphertext using the `nonce` (explicitly, when passed as a
|
||||
parameter or implicitly, when omitted, as part of the ciphertext) and
|
||||
returns the plaintext message.
|
||||
|
||||
:param ciphertext: [:class:`bytes`] The encrypted message to decrypt
|
||||
:param nonce: [:class:`bytes`] The nonce used when encrypting the
|
||||
ciphertext
|
||||
:param encoder: The encoder used to decode the ciphertext.
|
||||
:rtype: [:class:`bytes`]
|
||||
"""
|
||||
# Decode our ciphertext
|
||||
ciphertext = encoder.decode(ciphertext)
|
||||
|
||||
if nonce is None:
|
||||
# If we were given the nonce and ciphertext combined, split them.
|
||||
nonce = ciphertext[: self.NONCE_SIZE]
|
||||
ciphertext = ciphertext[self.NONCE_SIZE :]
|
||||
|
||||
if len(nonce) != self.NONCE_SIZE:
|
||||
raise exc.ValueError(
|
||||
"The nonce must be exactly %s bytes long" % self.NONCE_SIZE,
|
||||
)
|
||||
|
||||
plaintext = nacl.bindings.crypto_secretbox_open(
|
||||
ciphertext, nonce, self._key
|
||||
)
|
||||
|
||||
return plaintext
|
||||
|
||||
|
||||
class Aead(encoding.Encodable, StringFixer):
|
||||
"""
|
||||
The AEAD class encrypts and decrypts messages using the given secret key.
|
||||
|
||||
Unlike :class:`~nacl.secret.SecretBox`, AEAD supports authenticating
|
||||
non-confidential data received alongside the message, such as a length
|
||||
or type tag.
|
||||
|
||||
Like :class:`~nacl.secret.Secretbox`, this class provides authenticated
|
||||
encryption. An inauthentic message will cause the decrypt function to raise
|
||||
an exception.
|
||||
|
||||
Likewise, the authenticator should not be mistaken for a (public-key)
|
||||
signature: recipients (with the ability to decrypt messages) are capable of
|
||||
creating arbitrary valid message; in particular, this means AEAD messages
|
||||
are repudiable. For non-repudiable messages, sign them after encryption.
|
||||
|
||||
The cryptosystem used is `XChacha20-Poly1305`_ as specified for
|
||||
`standardization`_. There are `no practical limits`_ to how much can safely
|
||||
be encrypted under a given key (up to 2⁶⁴ messages each containing up
|
||||
to 2⁶⁴ bytes).
|
||||
|
||||
.. _standardization: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha
|
||||
.. _XChacha20-Poly1305: https://doc.libsodium.org/secret-key_cryptography/aead#xchacha-20-poly1305
|
||||
.. _no practical limits: https://doc.libsodium.org/secret-key_cryptography/aead#limitations
|
||||
|
||||
:param key: The secret key used to encrypt and decrypt messages
|
||||
:param encoder: The encoder class used to decode the given key
|
||||
|
||||
:cvar KEY_SIZE: The size that the key is required to be.
|
||||
:cvar NONCE_SIZE: The size that the nonce is required to be.
|
||||
:cvar MACBYTES: The size of the authentication MAC tag in bytes.
|
||||
:cvar MESSAGEBYTES_MAX: The maximum size of a message which can be
|
||||
safely encrypted with a single key/nonce
|
||||
pair.
|
||||
"""
|
||||
|
||||
KEY_SIZE = nacl.bindings.crypto_aead_xchacha20poly1305_ietf_KEYBYTES
|
||||
NONCE_SIZE = nacl.bindings.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
|
||||
MACBYTES = nacl.bindings.crypto_aead_xchacha20poly1305_ietf_ABYTES
|
||||
MESSAGEBYTES_MAX = (
|
||||
nacl.bindings.crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
key: bytes,
|
||||
encoder: encoding.Encoder = encoding.RawEncoder,
|
||||
):
|
||||
key = encoder.decode(key)
|
||||
if not isinstance(key, bytes):
|
||||
raise exc.TypeError("AEAD must be created from 32 bytes")
|
||||
|
||||
if len(key) != self.KEY_SIZE:
|
||||
raise exc.ValueError(
|
||||
"The key must be exactly %s bytes long" % self.KEY_SIZE,
|
||||
)
|
||||
|
||||
self._key = key
|
||||
|
||||
def __bytes__(self) -> bytes:
|
||||
return self._key
|
||||
|
||||
def encrypt(
|
||||
self,
|
||||
plaintext: bytes,
|
||||
aad: bytes = b"",
|
||||
nonce: Optional[bytes] = None,
|
||||
encoder: encoding.Encoder = encoding.RawEncoder,
|
||||
) -> EncryptedMessage:
|
||||
"""
|
||||
Encrypts the plaintext message using the given `nonce` (or generates
|
||||
one randomly if omitted) and returns the ciphertext encoded with the
|
||||
encoder.
|
||||
|
||||
.. warning:: It is vitally important for :param nonce: to be unique.
|
||||
By default, it is generated randomly; [:class:`Aead`] uses XChacha20
|
||||
for extended (192b) nonce size, so the risk of reusing random nonces
|
||||
is negligible. It is *strongly recommended* to keep this behaviour,
|
||||
as nonce reuse will compromise the privacy of encrypted messages.
|
||||
Should implicit nonces be inadequate for your application, the
|
||||
second best option is using split counters; e.g. if sending messages
|
||||
encrypted under a shared key between 2 users, each user can use the
|
||||
number of messages it sent so far, prefixed or suffixed with a 1bit
|
||||
user id. Note that the counter must **never** be rolled back (due
|
||||
to overflow, on-disk state being rolled back to an earlier backup,
|
||||
...)
|
||||
|
||||
:param plaintext: [:class:`bytes`] The plaintext message to encrypt
|
||||
:param nonce: [:class:`bytes`] The nonce to use in the encryption
|
||||
:param encoder: The encoder to use to encode the ciphertext
|
||||
:rtype: [:class:`nacl.utils.EncryptedMessage`]
|
||||
"""
|
||||
if nonce is None:
|
||||
nonce = random(self.NONCE_SIZE)
|
||||
|
||||
if len(nonce) != self.NONCE_SIZE:
|
||||
raise exc.ValueError(
|
||||
"The nonce must be exactly %s bytes long" % self.NONCE_SIZE,
|
||||
)
|
||||
|
||||
ciphertext = nacl.bindings.crypto_aead_xchacha20poly1305_ietf_encrypt(
|
||||
plaintext, aad, nonce, self._key
|
||||
)
|
||||
|
||||
encoded_nonce = encoder.encode(nonce)
|
||||
encoded_ciphertext = encoder.encode(ciphertext)
|
||||
|
||||
return EncryptedMessage._from_parts(
|
||||
encoded_nonce,
|
||||
encoded_ciphertext,
|
||||
encoder.encode(nonce + ciphertext),
|
||||
)
|
||||
|
||||
def decrypt(
|
||||
self,
|
||||
ciphertext: bytes,
|
||||
aad: bytes = b"",
|
||||
nonce: Optional[bytes] = None,
|
||||
encoder: encoding.Encoder = encoding.RawEncoder,
|
||||
) -> bytes:
|
||||
"""
|
||||
Decrypts the ciphertext using the `nonce` (explicitly, when passed as a
|
||||
parameter or implicitly, when omitted, as part of the ciphertext) and
|
||||
returns the plaintext message.
|
||||
|
||||
:param ciphertext: [:class:`bytes`] The encrypted message to decrypt
|
||||
:param nonce: [:class:`bytes`] The nonce used when encrypting the
|
||||
ciphertext
|
||||
:param encoder: The encoder used to decode the ciphertext.
|
||||
:rtype: [:class:`bytes`]
|
||||
"""
|
||||
# Decode our ciphertext
|
||||
ciphertext = encoder.decode(ciphertext)
|
||||
|
||||
if nonce is None:
|
||||
# If we were given the nonce and ciphertext combined, split them.
|
||||
nonce = ciphertext[: self.NONCE_SIZE]
|
||||
ciphertext = ciphertext[self.NONCE_SIZE :]
|
||||
|
||||
if len(nonce) != self.NONCE_SIZE:
|
||||
raise exc.ValueError(
|
||||
"The nonce must be exactly %s bytes long" % self.NONCE_SIZE,
|
||||
)
|
||||
|
||||
plaintext = nacl.bindings.crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||
ciphertext, aad, nonce, self._key
|
||||
)
|
||||
|
||||
return plaintext
|
250
venv/lib/python3.11/site-packages/nacl/signing.py
Normal file
250
venv/lib/python3.11/site-packages/nacl/signing.py
Normal file
@ -0,0 +1,250 @@
|
||||
# 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 Optional
|
||||
|
||||
import nacl.bindings
|
||||
from nacl import encoding
|
||||
from nacl import exceptions as exc
|
||||
from nacl.public import (
|
||||
PrivateKey as _Curve25519_PrivateKey,
|
||||
PublicKey as _Curve25519_PublicKey,
|
||||
)
|
||||
from nacl.utils import StringFixer, random
|
||||
|
||||
|
||||
class SignedMessage(bytes):
|
||||
"""
|
||||
A bytes subclass that holds a messaged that has been signed by a
|
||||
:class:`SigningKey`.
|
||||
"""
|
||||
|
||||
_signature: bytes
|
||||
_message: bytes
|
||||
|
||||
@classmethod
|
||||
def _from_parts(
|
||||
cls, signature: bytes, message: bytes, combined: bytes
|
||||
) -> "SignedMessage":
|
||||
obj = cls(combined)
|
||||
obj._signature = signature
|
||||
obj._message = message
|
||||
return obj
|
||||
|
||||
@property
|
||||
def signature(self) -> bytes:
|
||||
"""
|
||||
The signature contained within the :class:`SignedMessage`.
|
||||
"""
|
||||
return self._signature
|
||||
|
||||
@property
|
||||
def message(self) -> bytes:
|
||||
"""
|
||||
The message contained within the :class:`SignedMessage`.
|
||||
"""
|
||||
return self._message
|
||||
|
||||
|
||||
class VerifyKey(encoding.Encodable, StringFixer):
|
||||
"""
|
||||
The public key counterpart to an Ed25519 SigningKey for producing digital
|
||||
signatures.
|
||||
|
||||
:param key: [:class:`bytes`] Serialized Ed25519 public key
|
||||
:param encoder: A class that is able to decode the `key`
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, key: bytes, encoder: encoding.Encoder = encoding.RawEncoder
|
||||
):
|
||||
# Decode the key
|
||||
key = encoder.decode(key)
|
||||
if not isinstance(key, bytes):
|
||||
raise exc.TypeError("VerifyKey must be created from 32 bytes")
|
||||
|
||||
if len(key) != nacl.bindings.crypto_sign_PUBLICKEYBYTES:
|
||||
raise exc.ValueError(
|
||||
"The key must be exactly %s bytes long"
|
||||
% nacl.bindings.crypto_sign_PUBLICKEYBYTES,
|
||||
)
|
||||
|
||||
self._key = key
|
||||
|
||||
def __bytes__(self) -> bytes:
|
||||
return self._key
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return hash(bytes(self))
|
||||
|
||||
def __eq__(self, other: object) -> bool:
|
||||
if not isinstance(other, self.__class__):
|
||||
return False
|
||||
return nacl.bindings.sodium_memcmp(bytes(self), bytes(other))
|
||||
|
||||
def __ne__(self, other: object) -> bool:
|
||||
return not (self == other)
|
||||
|
||||
def verify(
|
||||
self,
|
||||
smessage: bytes,
|
||||
signature: Optional[bytes] = None,
|
||||
encoder: encoding.Encoder = encoding.RawEncoder,
|
||||
) -> bytes:
|
||||
"""
|
||||
Verifies the signature of a signed message, returning the message
|
||||
if it has not been tampered with else raising
|
||||
:class:`~nacl.signing.BadSignatureError`.
|
||||
|
||||
:param smessage: [:class:`bytes`] Either the original messaged or a
|
||||
signature and message concated together.
|
||||
:param signature: [:class:`bytes`] If an unsigned message is given for
|
||||
smessage then the detached signature must be provided.
|
||||
:param encoder: A class that is able to decode the secret message and
|
||||
signature.
|
||||
:rtype: :class:`bytes`
|
||||
"""
|
||||
if signature is not None:
|
||||
# If we were given the message and signature separately, validate
|
||||
# signature size and combine them.
|
||||
if not isinstance(signature, bytes):
|
||||
raise exc.TypeError(
|
||||
"Verification signature must be created from %d bytes"
|
||||
% nacl.bindings.crypto_sign_BYTES,
|
||||
)
|
||||
|
||||
if len(signature) != nacl.bindings.crypto_sign_BYTES:
|
||||
raise exc.ValueError(
|
||||
"The signature must be exactly %d bytes long"
|
||||
% nacl.bindings.crypto_sign_BYTES,
|
||||
)
|
||||
|
||||
smessage = signature + encoder.decode(smessage)
|
||||
else:
|
||||
# Decode the signed message
|
||||
smessage = encoder.decode(smessage)
|
||||
|
||||
return nacl.bindings.crypto_sign_open(smessage, self._key)
|
||||
|
||||
def to_curve25519_public_key(self) -> _Curve25519_PublicKey:
|
||||
"""
|
||||
Converts a :class:`~nacl.signing.VerifyKey` to a
|
||||
:class:`~nacl.public.PublicKey`
|
||||
|
||||
:rtype: :class:`~nacl.public.PublicKey`
|
||||
"""
|
||||
raw_pk = nacl.bindings.crypto_sign_ed25519_pk_to_curve25519(self._key)
|
||||
return _Curve25519_PublicKey(raw_pk)
|
||||
|
||||
|
||||
class SigningKey(encoding.Encodable, StringFixer):
|
||||
"""
|
||||
Private key for producing digital signatures using the Ed25519 algorithm.
|
||||
|
||||
Signing keys are produced from a 32-byte (256-bit) random seed value. This
|
||||
value can be passed into the :class:`~nacl.signing.SigningKey` as a
|
||||
:func:`bytes` whose length is 32.
|
||||
|
||||
.. warning:: This **must** be protected and remain secret. Anyone who knows
|
||||
the value of your :class:`~nacl.signing.SigningKey` or it's seed can
|
||||
masquerade as you.
|
||||
|
||||
:param seed: [:class:`bytes`] Random 32-byte value (i.e. private key)
|
||||
:param encoder: A class that is able to decode the seed
|
||||
|
||||
:ivar: verify_key: [:class:`~nacl.signing.VerifyKey`] The verify
|
||||
(i.e. public) key that corresponds with this signing key.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
seed: bytes,
|
||||
encoder: encoding.Encoder = encoding.RawEncoder,
|
||||
):
|
||||
# Decode the seed
|
||||
seed = encoder.decode(seed)
|
||||
if not isinstance(seed, bytes):
|
||||
raise exc.TypeError(
|
||||
"SigningKey must be created from a 32 byte seed"
|
||||
)
|
||||
|
||||
# Verify that our seed is the proper size
|
||||
if len(seed) != nacl.bindings.crypto_sign_SEEDBYTES:
|
||||
raise exc.ValueError(
|
||||
"The seed must be exactly %d bytes long"
|
||||
% nacl.bindings.crypto_sign_SEEDBYTES
|
||||
)
|
||||
|
||||
public_key, secret_key = nacl.bindings.crypto_sign_seed_keypair(seed)
|
||||
|
||||
self._seed = seed
|
||||
self._signing_key = secret_key
|
||||
self.verify_key = VerifyKey(public_key)
|
||||
|
||||
def __bytes__(self) -> bytes:
|
||||
return self._seed
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return hash(bytes(self))
|
||||
|
||||
def __eq__(self, other: object) -> bool:
|
||||
if not isinstance(other, self.__class__):
|
||||
return False
|
||||
return nacl.bindings.sodium_memcmp(bytes(self), bytes(other))
|
||||
|
||||
def __ne__(self, other: object) -> bool:
|
||||
return not (self == other)
|
||||
|
||||
@classmethod
|
||||
def generate(cls) -> "SigningKey":
|
||||
"""
|
||||
Generates a random :class:`~nacl.signing.SigningKey` object.
|
||||
|
||||
:rtype: :class:`~nacl.signing.SigningKey`
|
||||
"""
|
||||
return cls(
|
||||
random(nacl.bindings.crypto_sign_SEEDBYTES),
|
||||
encoder=encoding.RawEncoder,
|
||||
)
|
||||
|
||||
def sign(
|
||||
self,
|
||||
message: bytes,
|
||||
encoder: encoding.Encoder = encoding.RawEncoder,
|
||||
) -> SignedMessage:
|
||||
"""
|
||||
Sign a message using this key.
|
||||
|
||||
:param message: [:class:`bytes`] The data to be signed.
|
||||
:param encoder: A class that is used to encode the signed message.
|
||||
:rtype: :class:`~nacl.signing.SignedMessage`
|
||||
"""
|
||||
raw_signed = nacl.bindings.crypto_sign(message, self._signing_key)
|
||||
|
||||
crypto_sign_BYTES = nacl.bindings.crypto_sign_BYTES
|
||||
signature = encoder.encode(raw_signed[:crypto_sign_BYTES])
|
||||
message = encoder.encode(raw_signed[crypto_sign_BYTES:])
|
||||
signed = encoder.encode(raw_signed)
|
||||
|
||||
return SignedMessage._from_parts(signature, message, signed)
|
||||
|
||||
def to_curve25519_private_key(self) -> _Curve25519_PrivateKey:
|
||||
"""
|
||||
Converts a :class:`~nacl.signing.SigningKey` to a
|
||||
:class:`~nacl.public.PrivateKey`
|
||||
|
||||
:rtype: :class:`~nacl.public.PrivateKey`
|
||||
"""
|
||||
sk = self._signing_key
|
||||
raw_private = nacl.bindings.crypto_sign_ed25519_sk_to_curve25519(sk)
|
||||
return _Curve25519_PrivateKey(raw_private)
|
88
venv/lib/python3.11/site-packages/nacl/utils.py
Normal file
88
venv/lib/python3.11/site-packages/nacl/utils.py
Normal file
@ -0,0 +1,88 @@
|
||||
# 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 os
|
||||
from typing import SupportsBytes, Type, TypeVar
|
||||
|
||||
import nacl.bindings
|
||||
from nacl import encoding
|
||||
|
||||
_EncryptedMessage = TypeVar("_EncryptedMessage", bound="EncryptedMessage")
|
||||
|
||||
|
||||
class EncryptedMessage(bytes):
|
||||
"""
|
||||
A bytes subclass that holds a messaged that has been encrypted by a
|
||||
:class:`SecretBox`.
|
||||
"""
|
||||
|
||||
_nonce: bytes
|
||||
_ciphertext: bytes
|
||||
|
||||
@classmethod
|
||||
def _from_parts(
|
||||
cls: Type[_EncryptedMessage],
|
||||
nonce: bytes,
|
||||
ciphertext: bytes,
|
||||
combined: bytes,
|
||||
) -> _EncryptedMessage:
|
||||
obj = cls(combined)
|
||||
obj._nonce = nonce
|
||||
obj._ciphertext = ciphertext
|
||||
return obj
|
||||
|
||||
@property
|
||||
def nonce(self) -> bytes:
|
||||
"""
|
||||
The nonce used during the encryption of the :class:`EncryptedMessage`.
|
||||
"""
|
||||
return self._nonce
|
||||
|
||||
@property
|
||||
def ciphertext(self) -> bytes:
|
||||
"""
|
||||
The ciphertext contained within the :class:`EncryptedMessage`.
|
||||
"""
|
||||
return self._ciphertext
|
||||
|
||||
|
||||
class StringFixer:
|
||||
def __str__(self: SupportsBytes) -> str:
|
||||
return str(self.__bytes__())
|
||||
|
||||
|
||||
def bytes_as_string(bytes_in: bytes) -> str:
|
||||
return bytes_in.decode("ascii")
|
||||
|
||||
|
||||
def random(size: int = 32) -> bytes:
|
||||
return os.urandom(size)
|
||||
|
||||
|
||||
def randombytes_deterministic(
|
||||
size: int, seed: bytes, encoder: encoding.Encoder = encoding.RawEncoder
|
||||
) -> bytes:
|
||||
"""
|
||||
Returns ``size`` number of deterministically generated pseudorandom bytes
|
||||
from a seed
|
||||
|
||||
:param size: int
|
||||
:param seed: bytes
|
||||
:param encoder: The encoder class used to encode the produced bytes
|
||||
:rtype: bytes
|
||||
"""
|
||||
raw_data = nacl.bindings.randombytes_buf_deterministic(size, seed)
|
||||
|
||||
return encoder.encode(raw_data)
|
Reference in New Issue
Block a user