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:
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)[:]
|
Reference in New Issue
Block a user