Init
im going to bed -=-
This commit is contained in:
508
lib/nacl/bindings/__init__.py
Normal file
508
lib/nacl/bindings/__init__.py
Normal file
@@ -0,0 +1,508 @@
|
||||
# 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_aegis128l_ABYTES,
|
||||
crypto_aead_aegis128l_KEYBYTES,
|
||||
crypto_aead_aegis128l_MESSAGEBYTES_MAX,
|
||||
crypto_aead_aegis128l_NPUBBYTES,
|
||||
crypto_aead_aegis128l_NSECBYTES,
|
||||
crypto_aead_aegis128l_decrypt,
|
||||
crypto_aead_aegis128l_encrypt,
|
||||
crypto_aead_aegis256_ABYTES,
|
||||
crypto_aead_aegis256_KEYBYTES,
|
||||
crypto_aead_aegis256_MESSAGEBYTES_MAX,
|
||||
crypto_aead_aegis256_NPUBBYTES,
|
||||
crypto_aead_aegis256_NSECBYTES,
|
||||
crypto_aead_aegis256_decrypt,
|
||||
crypto_aead_aegis256_encrypt,
|
||||
crypto_aead_aes256gcm_ABYTES,
|
||||
crypto_aead_aes256gcm_KEYBYTES,
|
||||
crypto_aead_aes256gcm_MESSAGEBYTES_MAX,
|
||||
crypto_aead_aes256gcm_NPUBBYTES,
|
||||
crypto_aead_aes256gcm_NSECBYTES,
|
||||
crypto_aead_aes256gcm_decrypt,
|
||||
crypto_aead_aes256gcm_encrypt,
|
||||
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_easy,
|
||||
crypto_box_easy_afternm,
|
||||
crypto_box_keypair,
|
||||
crypto_box_open,
|
||||
crypto_box_open_afternm,
|
||||
crypto_box_open_easy,
|
||||
crypto_box_open_easy_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_from_uniform,
|
||||
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_easy,
|
||||
crypto_secretbox_open,
|
||||
crypto_secretbox_open_easy,
|
||||
)
|
||||
from nacl.bindings.crypto_secretstream import (
|
||||
crypto_secretstream_xchacha20poly1305_ABYTES,
|
||||
crypto_secretstream_xchacha20poly1305_HEADERBYTES,
|
||||
crypto_secretstream_xchacha20poly1305_KEYBYTES,
|
||||
crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX,
|
||||
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_aegis128l_ABYTES",
|
||||
"crypto_aead_aegis128l_KEYBYTES",
|
||||
"crypto_aead_aegis128l_MESSAGEBYTES_MAX",
|
||||
"crypto_aead_aegis128l_NPUBBYTES",
|
||||
"crypto_aead_aegis128l_NSECBYTES",
|
||||
"crypto_aead_aegis128l_decrypt",
|
||||
"crypto_aead_aegis128l_encrypt",
|
||||
"crypto_aead_aegis256_ABYTES",
|
||||
"crypto_aead_aegis256_KEYBYTES",
|
||||
"crypto_aead_aegis256_MESSAGEBYTES_MAX",
|
||||
"crypto_aead_aegis256_NPUBBYTES",
|
||||
"crypto_aead_aegis256_NSECBYTES",
|
||||
"crypto_aead_aegis256_decrypt",
|
||||
"crypto_aead_aegis256_encrypt",
|
||||
"crypto_aead_aes256gcm_ABYTES",
|
||||
"crypto_aead_aes256gcm_KEYBYTES",
|
||||
"crypto_aead_aes256gcm_MESSAGEBYTES_MAX",
|
||||
"crypto_aead_aes256gcm_NPUBBYTES",
|
||||
"crypto_aead_aes256gcm_NSECBYTES",
|
||||
"crypto_aead_aes256gcm_decrypt",
|
||||
"crypto_aead_aes256gcm_encrypt",
|
||||
"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_easy",
|
||||
"crypto_box_easy_afternm",
|
||||
"crypto_box_open_easy",
|
||||
"crypto_box_open_easy_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_easy",
|
||||
"crypto_secretbox_open",
|
||||
"crypto_secretbox_open_easy",
|
||||
"crypto_secretstream_xchacha20poly1305_ABYTES",
|
||||
"crypto_secretstream_xchacha20poly1305_HEADERBYTES",
|
||||
"crypto_secretstream_xchacha20poly1305_KEYBYTES",
|
||||
"crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX",
|
||||
"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()
|
||||
BIN
lib/nacl/bindings/__pycache__/__init__.cpython-314.pyc
Normal file
BIN
lib/nacl/bindings/__pycache__/__init__.cpython-314.pyc
Normal file
Binary file not shown.
BIN
lib/nacl/bindings/__pycache__/crypto_aead.cpython-314.pyc
Normal file
BIN
lib/nacl/bindings/__pycache__/crypto_aead.cpython-314.pyc
Normal file
Binary file not shown.
BIN
lib/nacl/bindings/__pycache__/crypto_box.cpython-314.pyc
Normal file
BIN
lib/nacl/bindings/__pycache__/crypto_box.cpython-314.pyc
Normal file
Binary file not shown.
BIN
lib/nacl/bindings/__pycache__/crypto_core.cpython-314.pyc
Normal file
BIN
lib/nacl/bindings/__pycache__/crypto_core.cpython-314.pyc
Normal file
Binary file not shown.
BIN
lib/nacl/bindings/__pycache__/crypto_generichash.cpython-314.pyc
Normal file
BIN
lib/nacl/bindings/__pycache__/crypto_generichash.cpython-314.pyc
Normal file
Binary file not shown.
BIN
lib/nacl/bindings/__pycache__/crypto_hash.cpython-314.pyc
Normal file
BIN
lib/nacl/bindings/__pycache__/crypto_hash.cpython-314.pyc
Normal file
Binary file not shown.
BIN
lib/nacl/bindings/__pycache__/crypto_kx.cpython-314.pyc
Normal file
BIN
lib/nacl/bindings/__pycache__/crypto_kx.cpython-314.pyc
Normal file
Binary file not shown.
BIN
lib/nacl/bindings/__pycache__/crypto_pwhash.cpython-314.pyc
Normal file
BIN
lib/nacl/bindings/__pycache__/crypto_pwhash.cpython-314.pyc
Normal file
Binary file not shown.
BIN
lib/nacl/bindings/__pycache__/crypto_scalarmult.cpython-314.pyc
Normal file
BIN
lib/nacl/bindings/__pycache__/crypto_scalarmult.cpython-314.pyc
Normal file
Binary file not shown.
BIN
lib/nacl/bindings/__pycache__/crypto_secretbox.cpython-314.pyc
Normal file
BIN
lib/nacl/bindings/__pycache__/crypto_secretbox.cpython-314.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
lib/nacl/bindings/__pycache__/crypto_shorthash.cpython-314.pyc
Normal file
BIN
lib/nacl/bindings/__pycache__/crypto_shorthash.cpython-314.pyc
Normal file
Binary file not shown.
BIN
lib/nacl/bindings/__pycache__/crypto_sign.cpython-314.pyc
Normal file
BIN
lib/nacl/bindings/__pycache__/crypto_sign.cpython-314.pyc
Normal file
Binary file not shown.
BIN
lib/nacl/bindings/__pycache__/randombytes.cpython-314.pyc
Normal file
BIN
lib/nacl/bindings/__pycache__/randombytes.cpython-314.pyc
Normal file
Binary file not shown.
BIN
lib/nacl/bindings/__pycache__/sodium_core.cpython-314.pyc
Normal file
BIN
lib/nacl/bindings/__pycache__/sodium_core.cpython-314.pyc
Normal file
Binary file not shown.
BIN
lib/nacl/bindings/__pycache__/utils.cpython-314.pyc
Normal file
BIN
lib/nacl/bindings/__pycache__/utils.cpython-314.pyc
Normal file
Binary file not shown.
1069
lib/nacl/bindings/crypto_aead.py
Normal file
1069
lib/nacl/bindings/crypto_aead.py
Normal file
File diff suppressed because it is too large
Load Diff
475
lib/nacl/bindings/crypto_box.py
Normal file
475
lib/nacl/bindings/crypto_box.py
Normal file
@@ -0,0 +1,475 @@
|
||||
# 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()
|
||||
crypto_box_MACBYTES: int = lib.crypto_box_macbytes()
|
||||
|
||||
|
||||
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) key pair 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_easy(
|
||||
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")
|
||||
|
||||
_mlen = len(message)
|
||||
_clen = crypto_box_MACBYTES + _mlen
|
||||
|
||||
ciphertext = ffi.new("unsigned char[]", _clen)
|
||||
|
||||
rc = lib.crypto_box_easy(ciphertext, message, _mlen, nonce, pk, sk)
|
||||
ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
|
||||
|
||||
return ffi.buffer(ciphertext, _clen)[:]
|
||||
|
||||
|
||||
def crypto_box_open_easy(
|
||||
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")
|
||||
|
||||
_clen = len(ciphertext)
|
||||
|
||||
ensure(
|
||||
_clen >= crypto_box_MACBYTES,
|
||||
"Input ciphertext must be at least {} long".format(
|
||||
crypto_box_MACBYTES
|
||||
),
|
||||
raising=exc.TypeError,
|
||||
)
|
||||
|
||||
_mlen = _clen - crypto_box_MACBYTES
|
||||
|
||||
plaintext = ffi.new("unsigned char[]", max(1, _mlen))
|
||||
|
||||
res = lib.crypto_box_open_easy(plaintext, ciphertext, _clen, nonce, pk, sk)
|
||||
ensure(
|
||||
res == 0,
|
||||
"An error occurred trying to decrypt the message",
|
||||
raising=exc.CryptoError,
|
||||
)
|
||||
|
||||
return ffi.buffer(plaintext, _mlen)[:]
|
||||
|
||||
|
||||
def crypto_box_easy_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")
|
||||
|
||||
_mlen = len(message)
|
||||
_clen = crypto_box_MACBYTES + _mlen
|
||||
|
||||
ciphertext = ffi.new("unsigned char[]", _clen)
|
||||
|
||||
rc = lib.crypto_box_easy_afternm(ciphertext, message, _mlen, nonce, k)
|
||||
ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
|
||||
|
||||
return ffi.buffer(ciphertext, _clen)[:]
|
||||
|
||||
|
||||
def crypto_box_open_easy_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")
|
||||
|
||||
_clen = len(ciphertext)
|
||||
|
||||
ensure(
|
||||
_clen >= crypto_box_MACBYTES,
|
||||
"Input ciphertext must be at least {} long".format(
|
||||
crypto_box_MACBYTES
|
||||
),
|
||||
raising=exc.TypeError,
|
||||
)
|
||||
|
||||
_mlen = _clen - crypto_box_MACBYTES
|
||||
|
||||
plaintext = ffi.new("unsigned char[]", max(1, _mlen))
|
||||
|
||||
res = lib.crypto_box_open_easy_afternm(
|
||||
plaintext, ciphertext, _clen, nonce, k
|
||||
)
|
||||
ensure(
|
||||
res == 0,
|
||||
"An error occurred trying to decrypt the message",
|
||||
raising=exc.CryptoError,
|
||||
)
|
||||
|
||||
return ffi.buffer(plaintext, _mlen)[:]
|
||||
|
||||
|
||||
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 construct 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 ciphertext 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)[:]
|
||||
449
lib/nacl/bindings/crypto_core.py
Normal file
449
lib/nacl/bindings/crypto_core.py
Normal file
@@ -0,0 +1,449 @@
|
||||
# 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_from_uniform(r: bytes) -> bytes:
|
||||
"""
|
||||
Maps a 32 bytes vector ``r`` to a point. The point is guaranteed to be on the main subgroup.
|
||||
This function directly exposes the Elligator 2 map, uses the high bit to set
|
||||
the sign of the X coordinate, and the resulting point is multiplied by the cofactor.
|
||||
|
||||
:param r: a :py:data:`.crypto_core_ed25519_BYTES` long bytes
|
||||
sequence representing arbitrary data
|
||||
:type r: bytes
|
||||
:return: a point on the edwards25519 curve main order subgroup, 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(r, bytes) and len(r) == crypto_core_ed25519_BYTES,
|
||||
"Integer r must be a {} long bytes sequence".format(
|
||||
"crypto_core_ed25519_BYTES"
|
||||
),
|
||||
raising=exc.TypeError,
|
||||
)
|
||||
|
||||
p = ffi.new("unsigned char[]", crypto_core_ed25519_BYTES)
|
||||
|
||||
rc = lib.crypto_core_ed25519_from_uniform(p, r)
|
||||
ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError)
|
||||
|
||||
return ffi.buffer(p, crypto_core_ed25519_BYTES)[:]
|
||||
|
||||
|
||||
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)[:]
|
||||
281
lib/nacl/bindings/crypto_generichash.py
Normal file
281
lib/nacl/bindings/crypto_generichash.py
Normal file
@@ -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)[:]
|
||||
63
lib/nacl/bindings/crypto_hash.py
Normal file
63
lib/nacl/bindings/crypto_hash.py
Normal file
@@ -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
lib/nacl/bindings/crypto_kx.py
Normal file
200
lib/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 key pair.
|
||||
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 key pair 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)[:],
|
||||
)
|
||||
599
lib/nacl/bindings/crypto_pwhash.py
Normal file
599
lib/nacl/bindings/crypto_pwhash.py
Normal file
@@ -0,0 +1,599 @@
|
||||
# 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 chosen 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
|
||||
240
lib/nacl/bindings/crypto_scalarmult.py
Normal file
240
lib/nacl/bindings/crypto_scalarmult.py
Normal file
@@ -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)[:]
|
||||
159
lib/nacl/bindings/crypto_secretbox.py
Normal file
159
lib/nacl/bindings/crypto_secretbox.py
Normal file
@@ -0,0 +1,159 @@
|
||||
# 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:]
|
||||
|
||||
|
||||
def crypto_secretbox_easy(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")
|
||||
|
||||
_mlen = len(message)
|
||||
_clen = crypto_secretbox_MACBYTES + _mlen
|
||||
|
||||
ciphertext = ffi.new("unsigned char[]", _clen)
|
||||
|
||||
res = lib.crypto_secretbox_easy(ciphertext, message, _mlen, nonce, key)
|
||||
ensure(res == 0, "Encryption failed", raising=exc.CryptoError)
|
||||
|
||||
ciphertext = ffi.buffer(ciphertext, _clen)
|
||||
return ciphertext[:]
|
||||
|
||||
|
||||
def crypto_secretbox_open_easy(
|
||||
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")
|
||||
|
||||
_clen = len(ciphertext)
|
||||
|
||||
ensure(
|
||||
_clen >= crypto_secretbox_MACBYTES,
|
||||
"Input ciphertext must be at least {} long".format(
|
||||
crypto_secretbox_MACBYTES
|
||||
),
|
||||
raising=exc.TypeError,
|
||||
)
|
||||
|
||||
_mlen = _clen - crypto_secretbox_MACBYTES
|
||||
|
||||
plaintext = ffi.new("unsigned char[]", max(1, _mlen))
|
||||
|
||||
res = lib.crypto_secretbox_open_easy(
|
||||
plaintext, ciphertext, _clen, nonce, key
|
||||
)
|
||||
ensure(
|
||||
res == 0,
|
||||
"Decryption failed. Ciphertext failed verification",
|
||||
raising=exc.CryptoError,
|
||||
)
|
||||
|
||||
plaintext = ffi.buffer(plaintext, _mlen)
|
||||
return plaintext[:]
|
||||
358
lib/nacl/bindings/crypto_secretstream.py
Normal file
358
lib/nacl/bindings/crypto_secretstream.py
Normal file
@@ -0,0 +1,358 @@
|
||||
# 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 Optional, Tuple, Union, 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."""
|
||||
ByteString = Union[bytes, bytearray, memoryview]
|
||||
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)
|
||||
81
lib/nacl/bindings/crypto_shorthash.py
Normal file
81
lib/nacl/bindings/crypto_shorthash.py
Normal file
@@ -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
lib/nacl/bindings/crypto_sign.py
Normal file
327
lib/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 key (secret and public part)
|
||||
: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
|
||||
51
lib/nacl/bindings/randombytes.py
Normal file
51
lib/nacl/bindings/randombytes.py
Normal file
@@ -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)[:]
|
||||
33
lib/nacl/bindings/sodium_core.py
Normal file
33
lib/nacl/bindings/sodium_core.py
Normal file
@@ -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
lib/nacl/bindings/utils.py
Normal file
141
lib/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