First ansible commit

This commit is contained in:
2018-11-12 16:30:14 +08:00
commit 162b95eee7
8057 changed files with 1214120 additions and 0 deletions

View 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 __future__ import absolute_import, division, print_function
__all__ = [
"__title__", "__summary__", "__uri__", "__version__", "__author__",
"__email__", "__license__", "__copyright__",
]
__title__ = "PyNaCl"
__summary__ = ("Python binding to the Networking and Cryptography (NaCl) "
"library")
__uri__ = "https://github.com/pyca/pynacl/"
__version__ = "1.3.0"
__author__ = "The PyNaCl developers"
__email__ = "cryptography-dev@python.org"
__license__ = "Apache License 2.0"
__copyright__ = "Copyright 2013-2018 {0}".format(__author__)

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,377 @@
# 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 __future__ import absolute_import, division, print_function
from nacl.bindings.crypto_aead import (
crypto_aead_chacha20poly1305_ABYTES,
crypto_aead_chacha20poly1305_KEYBYTES,
crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX,
crypto_aead_chacha20poly1305_NPUBBYTES,
crypto_aead_chacha20poly1305_NSECBYTES,
crypto_aead_chacha20poly1305_decrypt,
crypto_aead_chacha20poly1305_encrypt,
crypto_aead_chacha20poly1305_ietf_ABYTES,
crypto_aead_chacha20poly1305_ietf_KEYBYTES,
crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX,
crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
crypto_aead_chacha20poly1305_ietf_NSECBYTES,
crypto_aead_chacha20poly1305_ietf_decrypt,
crypto_aead_chacha20poly1305_ietf_encrypt,
crypto_aead_xchacha20poly1305_ietf_ABYTES,
crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX,
crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
crypto_aead_xchacha20poly1305_ietf_NSECBYTES,
crypto_aead_xchacha20poly1305_ietf_decrypt,
crypto_aead_xchacha20poly1305_ietf_encrypt,
)
from nacl.bindings.crypto_box import (
crypto_box, crypto_box_BEFORENMBYTES, crypto_box_BOXZEROBYTES,
crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES, crypto_box_SEALBYTES,
crypto_box_SECRETKEYBYTES, crypto_box_SEEDBYTES, crypto_box_ZEROBYTES,
crypto_box_afternm, crypto_box_beforenm, crypto_box_keypair,
crypto_box_open, crypto_box_open_afternm, crypto_box_seal,
crypto_box_seal_open, crypto_box_seed_keypair,
)
from nacl.bindings.crypto_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_state_copy as crypto_generichash_blake2b_state_copy,
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,
nacl_bindings_pick_scrypt_params,
)
from nacl.bindings.crypto_scalarmult import (
crypto_scalarmult, crypto_scalarmult_BYTES, crypto_scalarmult_SCALARBYTES,
crypto_scalarmult_base
)
from nacl.bindings.crypto_secretbox import (
crypto_secretbox, crypto_secretbox_BOXZEROBYTES, crypto_secretbox_KEYBYTES,
crypto_secretbox_MACBYTES, crypto_secretbox_MESSAGEBYTES_MAX,
crypto_secretbox_NONCEBYTES, crypto_secretbox_ZEROBYTES,
crypto_secretbox_open
)
from nacl.bindings.crypto_secretstream import (
crypto_secretstream_xchacha20poly1305_ABYTES,
crypto_secretstream_xchacha20poly1305_HEADERBYTES,
crypto_secretstream_xchacha20poly1305_KEYBYTES,
crypto_secretstream_xchacha20poly1305_STATEBYTES,
crypto_secretstream_xchacha20poly1305_TAG_FINAL,
crypto_secretstream_xchacha20poly1305_TAG_MESSAGE,
crypto_secretstream_xchacha20poly1305_TAG_PUSH,
crypto_secretstream_xchacha20poly1305_TAG_REKEY,
crypto_secretstream_xchacha20poly1305_init_pull,
crypto_secretstream_xchacha20poly1305_init_push,
crypto_secretstream_xchacha20poly1305_keygen,
crypto_secretstream_xchacha20poly1305_pull,
crypto_secretstream_xchacha20poly1305_push,
crypto_secretstream_xchacha20poly1305_rekey,
crypto_secretstream_xchacha20poly1305_state,
)
from nacl.bindings.crypto_shorthash import (
BYTES as crypto_shorthash_siphash24_BYTES,
KEYBYTES as crypto_shorthash_siphash24_KEYBYTES,
XBYTES as crypto_shorthash_siphashx24_BYTES,
XKEYBYTES as crypto_shorthash_siphashx24_KEYBYTES,
crypto_shorthash_siphash24,
crypto_shorthash_siphashx24
)
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_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
from nacl.bindings.sodium_core import sodium_init
from nacl.bindings.utils import (
sodium_add, sodium_increment, sodium_memcmp, sodium_pad, sodium_unpad,
)
__all__ = [
"crypto_aead_chacha20poly1305_ABYTES",
"crypto_aead_chacha20poly1305_KEYBYTES",
"crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX",
"crypto_aead_chacha20poly1305_NPUBBYTES",
"crypto_aead_chacha20poly1305_NSECBYTES",
"crypto_aead_chacha20poly1305_decrypt",
"crypto_aead_chacha20poly1305_encrypt",
"crypto_aead_chacha20poly1305_ietf_ABYTES",
"crypto_aead_chacha20poly1305_ietf_KEYBYTES",
"crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX",
"crypto_aead_chacha20poly1305_ietf_NPUBBYTES",
"crypto_aead_chacha20poly1305_ietf_NSECBYTES",
"crypto_aead_chacha20poly1305_ietf_decrypt",
"crypto_aead_chacha20poly1305_ietf_encrypt",
"crypto_aead_xchacha20poly1305_ietf_ABYTES",
"crypto_aead_xchacha20poly1305_ietf_KEYBYTES",
"crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX",
"crypto_aead_xchacha20poly1305_ietf_NPUBBYTES",
"crypto_aead_xchacha20poly1305_ietf_NSECBYTES",
"crypto_aead_xchacha20poly1305_ietf_decrypt",
"crypto_aead_xchacha20poly1305_ietf_encrypt",
"crypto_box_SECRETKEYBYTES",
"crypto_box_PUBLICKEYBYTES",
"crypto_box_SEEDBYTES",
"crypto_box_NONCEBYTES",
"crypto_box_ZEROBYTES",
"crypto_box_BOXZEROBYTES",
"crypto_box_BEFORENMBYTES",
"crypto_box_SEALBYTES",
"crypto_box_keypair",
"crypto_box",
"crypto_box_open",
"crypto_box_beforenm",
"crypto_box_afternm",
"crypto_box_open_afternm",
"crypto_box_seal",
"crypto_box_seal_open",
"crypto_box_seed_keypair",
"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_generichash_blake2b_state_copy",
"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",
"crypto_scalarmult_BYTES",
"crypto_scalarmult_SCALARBYTES",
"crypto_scalarmult",
"crypto_scalarmult_base",
"crypto_secretbox_KEYBYTES",
"crypto_secretbox_NONCEBYTES",
"crypto_secretbox_ZEROBYTES",
"crypto_secretbox_BOXZEROBYTES",
"crypto_secretbox_MACBYTES",
"crypto_secretbox_MESSAGEBYTES_MAX",
"crypto_secretbox",
"crypto_secretbox_open",
"crypto_secretstream_xchacha20poly1305_ABYTES",
"crypto_secretstream_xchacha20poly1305_HEADERBYTES",
"crypto_secretstream_xchacha20poly1305_KEYBYTES",
"crypto_secretstream_xchacha20poly1305_STATEBYTES",
"crypto_secretstream_xchacha20poly1305_TAG_FINAL",
"crypto_secretstream_xchacha20poly1305_TAG_MESSAGE",
"crypto_secretstream_xchacha20poly1305_TAG_PUSH",
"crypto_secretstream_xchacha20poly1305_TAG_REKEY",
"crypto_secretstream_xchacha20poly1305_init_pull",
"crypto_secretstream_xchacha20poly1305_init_push",
"crypto_secretstream_xchacha20poly1305_keygen",
"crypto_secretstream_xchacha20poly1305_pull",
"crypto_secretstream_xchacha20poly1305_push",
"crypto_secretstream_xchacha20poly1305_rekey",
"crypto_secretstream_xchacha20poly1305_state",
"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_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",
"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",
"sodium_init",
"sodium_add",
"sodium_increment",
"sodium_memcmp",
"sodium_pad",
"sodium_unpad",
]
# Initialize Sodium
sodium_init()

View File

@@ -0,0 +1,485 @@
# Copyright 2017 Donald Stufft and individual contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import, division, print_function
from nacl import exceptions as exc
from nacl._sodium import ffi, lib
from nacl.exceptions import ensure
"""
Implementations of authenticated encription with associated data (*AEAD*)
constructions building on the chacha20 stream cipher and the poly1305
authenticator
"""
crypto_aead_chacha20poly1305_ietf_KEYBYTES = \
lib.crypto_aead_chacha20poly1305_ietf_keybytes()
crypto_aead_chacha20poly1305_ietf_NSECBYTES = \
lib.crypto_aead_chacha20poly1305_ietf_nsecbytes()
crypto_aead_chacha20poly1305_ietf_NPUBBYTES = \
lib.crypto_aead_chacha20poly1305_ietf_npubbytes()
crypto_aead_chacha20poly1305_ietf_ABYTES = \
lib.crypto_aead_chacha20poly1305_ietf_abytes()
crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX = \
lib.crypto_aead_chacha20poly1305_ietf_messagebytes_max()
_aead_chacha20poly1305_ietf_CRYPTBYTES_MAX = \
crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX + \
crypto_aead_chacha20poly1305_ietf_ABYTES
crypto_aead_chacha20poly1305_KEYBYTES = \
lib.crypto_aead_chacha20poly1305_keybytes()
crypto_aead_chacha20poly1305_NSECBYTES = \
lib.crypto_aead_chacha20poly1305_nsecbytes()
crypto_aead_chacha20poly1305_NPUBBYTES = \
lib.crypto_aead_chacha20poly1305_npubbytes()
crypto_aead_chacha20poly1305_ABYTES = \
lib.crypto_aead_chacha20poly1305_abytes()
crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX = \
lib.crypto_aead_chacha20poly1305_messagebytes_max()
_aead_chacha20poly1305_CRYPTBYTES_MAX = \
crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX + \
crypto_aead_chacha20poly1305_ABYTES
crypto_aead_xchacha20poly1305_ietf_KEYBYTES = \
lib.crypto_aead_xchacha20poly1305_ietf_keybytes()
crypto_aead_xchacha20poly1305_ietf_NSECBYTES = \
lib.crypto_aead_xchacha20poly1305_ietf_nsecbytes()
crypto_aead_xchacha20poly1305_ietf_NPUBBYTES = \
lib.crypto_aead_xchacha20poly1305_ietf_npubbytes()
crypto_aead_xchacha20poly1305_ietf_ABYTES = \
lib.crypto_aead_xchacha20poly1305_ietf_abytes()
crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX = \
lib.crypto_aead_xchacha20poly1305_ietf_messagebytes_max()
_aead_xchacha20poly1305_ietf_CRYPTBYTES_MAX = \
crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX + \
crypto_aead_xchacha20poly1305_ietf_ABYTES
def crypto_aead_chacha20poly1305_ietf_encrypt(message, aad, nonce, key):
"""
Encrypt the given ``message`` using the IETF ratified chacha20poly1305
construction described in RFC7539.
:param message:
:type message: bytes
:param aad:
:type aad: bytes
:param nonce:
:type nonce: bytes
:param key:
:type key: bytes
:return: authenticated ciphertext
:rtype: bytes
"""
ensure(isinstance(message, bytes), 'Input message type must be bytes',
raising=exc.TypeError)
mlen = len(message)
ensure(mlen <= crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX,
'Message must be at most {0} bytes long'.format(
crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX),
raising=exc.ValueError)
ensure(isinstance(aad, bytes) or (aad is None),
'Additional data must be bytes or None',
raising=exc.TypeError)
ensure(isinstance(nonce, bytes) and
len(nonce) == crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
'Nonce must be a {0} bytes long bytes sequence'.format(
crypto_aead_chacha20poly1305_ietf_NPUBBYTES),
raising=exc.TypeError)
ensure(isinstance(key, bytes) and
len(key) == crypto_aead_chacha20poly1305_ietf_KEYBYTES,
'Key must be a {0} bytes long bytes sequence'.format(
crypto_aead_chacha20poly1305_ietf_KEYBYTES),
raising=exc.TypeError)
if aad:
_aad = aad
aalen = len(aad)
else:
_aad = ffi.NULL
aalen = 0
mxout = mlen + crypto_aead_chacha20poly1305_ietf_ABYTES
clen = ffi.new("unsigned long long *")
ciphertext = ffi.new("unsigned char[]", mxout)
res = lib.crypto_aead_chacha20poly1305_ietf_encrypt(ciphertext,
clen,
message,
mlen,
_aad,
aalen,
ffi.NULL,
nonce,
key)
ensure(res == 0, "Encryption failed.", raising=exc.CryptoError)
return ffi.buffer(ciphertext, clen[0])[:]
def crypto_aead_chacha20poly1305_ietf_decrypt(ciphertext, aad, nonce, key):
"""
Decrypt the given ``ciphertext`` using the IETF ratified chacha20poly1305
construction described in RFC7539.
:param ciphertext:
:type ciphertext: bytes
:param aad:
:type aad: bytes
:param nonce:
:type nonce: bytes
:param key:
:type key: bytes
:return: message
:rtype: bytes
"""
ensure(isinstance(ciphertext, bytes),
'Input ciphertext type must be bytes',
raising=exc.TypeError)
clen = len(ciphertext)
ensure(clen <= _aead_chacha20poly1305_ietf_CRYPTBYTES_MAX,
'Ciphertext must be at most {0} bytes long'.format(
_aead_chacha20poly1305_ietf_CRYPTBYTES_MAX),
raising=exc.ValueError)
ensure(isinstance(aad, bytes) or (aad is None),
'Additional data must be bytes or None',
raising=exc.TypeError)
ensure(isinstance(nonce, bytes) and
len(nonce) == crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
'Nonce must be a {0} bytes long bytes sequence'.format(
crypto_aead_chacha20poly1305_ietf_NPUBBYTES),
raising=exc.TypeError)
ensure(isinstance(key, bytes) and
len(key) == crypto_aead_chacha20poly1305_ietf_KEYBYTES,
'Key must be a {0} bytes long bytes sequence'.format(
crypto_aead_chacha20poly1305_ietf_KEYBYTES),
raising=exc.TypeError)
mxout = clen - crypto_aead_chacha20poly1305_ietf_ABYTES
mlen = ffi.new("unsigned long long *")
message = ffi.new("unsigned char[]", mxout)
if aad:
_aad = aad
aalen = len(aad)
else:
_aad = ffi.NULL
aalen = 0
res = lib.crypto_aead_chacha20poly1305_ietf_decrypt(message,
mlen,
ffi.NULL,
ciphertext,
clen,
_aad,
aalen,
nonce,
key)
ensure(res == 0, "Decryption failed.", raising=exc.CryptoError)
return ffi.buffer(message, mlen[0])[:]
def crypto_aead_chacha20poly1305_encrypt(message, aad, nonce, key):
"""
Encrypt the given ``message`` using the "legacy" construction
described in draft-agl-tls-chacha20poly1305.
:param message:
:type message: bytes
:param aad:
:type aad: bytes
:param nonce:
:type nonce: bytes
:param key:
:type key: bytes
:return: authenticated ciphertext
:rtype: bytes
"""
ensure(isinstance(message, bytes), 'Input message type must be bytes',
raising=exc.TypeError)
mlen = len(message)
ensure(mlen <= crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX,
'Message must be at most {0} bytes long'.format(
crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX),
raising=exc.ValueError)
ensure(isinstance(aad, bytes) or (aad is None),
'Additional data must be bytes or None',
raising=exc.TypeError)
ensure(isinstance(nonce, bytes) and
len(nonce) == crypto_aead_chacha20poly1305_NPUBBYTES,
'Nonce must be a {0} bytes long bytes sequence'.format(
crypto_aead_chacha20poly1305_NPUBBYTES),
raising=exc.TypeError)
ensure(isinstance(key, bytes) and
len(key) == crypto_aead_chacha20poly1305_KEYBYTES,
'Key must be a {0} bytes long bytes sequence'.format(
crypto_aead_chacha20poly1305_KEYBYTES),
raising=exc.TypeError)
if aad:
_aad = aad
aalen = len(aad)
else:
_aad = ffi.NULL
aalen = 0
mlen = len(message)
mxout = mlen + crypto_aead_chacha20poly1305_ietf_ABYTES
clen = ffi.new("unsigned long long *")
ciphertext = ffi.new("unsigned char[]", mxout)
res = lib.crypto_aead_chacha20poly1305_encrypt(ciphertext,
clen,
message,
mlen,
_aad,
aalen,
ffi.NULL,
nonce,
key)
ensure(res == 0, "Encryption failed.", raising=exc.CryptoError)
return ffi.buffer(ciphertext, clen[0])[:]
def crypto_aead_chacha20poly1305_decrypt(ciphertext, aad, nonce, key):
"""
Decrypt the given ``ciphertext`` using the "legacy" construction
described in draft-agl-tls-chacha20poly1305.
:param ciphertext: authenticated ciphertext
:type ciphertext: bytes
:param aad:
:type aad: bytes
:param nonce:
:type nonce: bytes
:param key:
:type key: bytes
:return: message
:rtype: bytes
"""
ensure(isinstance(ciphertext, bytes),
'Input ciphertext type must be bytes',
raising=exc.TypeError)
clen = len(ciphertext)
ensure(clen <= _aead_chacha20poly1305_CRYPTBYTES_MAX,
'Ciphertext must be at most {0} bytes long'.format(
_aead_chacha20poly1305_CRYPTBYTES_MAX),
raising=exc.ValueError)
ensure(isinstance(aad, bytes) or (aad is None),
'Additional data must be bytes or None',
raising=exc.TypeError)
ensure(isinstance(nonce, bytes) and
len(nonce) == crypto_aead_chacha20poly1305_NPUBBYTES,
'Nonce must be a {0} bytes long bytes sequence'.format(
crypto_aead_chacha20poly1305_NPUBBYTES),
raising=exc.TypeError)
ensure(isinstance(key, bytes) and
len(key) == crypto_aead_chacha20poly1305_KEYBYTES,
'Key must be a {0} bytes long bytes sequence'.format(
crypto_aead_chacha20poly1305_KEYBYTES),
raising=exc.TypeError)
mxout = clen - crypto_aead_chacha20poly1305_ABYTES
mlen = ffi.new("unsigned long long *")
message = ffi.new("unsigned char[]", mxout)
if aad:
_aad = aad
aalen = len(aad)
else:
_aad = ffi.NULL
aalen = 0
res = lib.crypto_aead_chacha20poly1305_decrypt(message,
mlen,
ffi.NULL,
ciphertext,
clen,
_aad,
aalen,
nonce,
key)
ensure(res == 0, "Decryption failed.", raising=exc.CryptoError)
return ffi.buffer(message, mlen[0])[:]
def crypto_aead_xchacha20poly1305_ietf_encrypt(message, aad, nonce, key):
"""
Encrypt the given ``message`` using the long-nonces xchacha20poly1305
construction.
:param message:
:type message: bytes
:param aad:
:type aad: bytes
:param nonce:
:type nonce: bytes
:param key:
:type key: bytes
:return: authenticated ciphertext
:rtype: bytes
"""
ensure(isinstance(message, bytes), 'Input message type must be bytes',
raising=exc.TypeError)
mlen = len(message)
ensure(mlen <= crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX,
'Message must be at most {0} bytes long'.format(
crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX),
raising=exc.ValueError)
ensure(isinstance(aad, bytes) or (aad is None),
'Additional data must be bytes or None',
raising=exc.TypeError)
ensure(isinstance(nonce, bytes) and
len(nonce) == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
'Nonce must be a {0} bytes long bytes sequence'.format(
crypto_aead_xchacha20poly1305_ietf_NPUBBYTES),
raising=exc.TypeError)
ensure(isinstance(key, bytes) and
len(key) == crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
'Key must be a {0} bytes long bytes sequence'.format(
crypto_aead_xchacha20poly1305_ietf_KEYBYTES),
raising=exc.TypeError)
if aad:
_aad = aad
aalen = len(aad)
else:
_aad = ffi.NULL
aalen = 0
mlen = len(message)
mxout = mlen + crypto_aead_xchacha20poly1305_ietf_ABYTES
clen = ffi.new("unsigned long long *")
ciphertext = ffi.new("unsigned char[]", mxout)
res = lib.crypto_aead_xchacha20poly1305_ietf_encrypt(ciphertext,
clen,
message,
mlen,
_aad,
aalen,
ffi.NULL,
nonce,
key)
ensure(res == 0, "Encryption failed.", raising=exc.CryptoError)
return ffi.buffer(ciphertext, clen[0])[:]
def crypto_aead_xchacha20poly1305_ietf_decrypt(ciphertext, aad, nonce, key):
"""
Decrypt the given ``ciphertext`` using the long-nonces xchacha20poly1305
construction.
:param ciphertext: authenticated ciphertext
:type ciphertext: bytes
:param aad:
:type aad: bytes
:param nonce:
:type nonce: bytes
:param key:
:type key: bytes
:return: message
:rtype: bytes
"""
ensure(isinstance(ciphertext, bytes),
'Input ciphertext type must be bytes',
raising=exc.TypeError)
clen = len(ciphertext)
ensure(clen <= _aead_xchacha20poly1305_ietf_CRYPTBYTES_MAX,
'Ciphertext must be at most {0} bytes long'.format(
_aead_xchacha20poly1305_ietf_CRYPTBYTES_MAX),
raising=exc.ValueError)
ensure(isinstance(aad, bytes) or (aad is None),
'Additional data must be bytes or None',
raising=exc.TypeError)
ensure(isinstance(nonce, bytes) and
len(nonce) == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
'Nonce must be a {0} bytes long bytes sequence'.format(
crypto_aead_xchacha20poly1305_ietf_NPUBBYTES),
raising=exc.TypeError)
ensure(isinstance(key, bytes) and
len(key) == crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
'Key must be a {0} bytes long bytes sequence'.format(
crypto_aead_xchacha20poly1305_ietf_KEYBYTES),
raising=exc.TypeError)
mxout = clen - crypto_aead_xchacha20poly1305_ietf_ABYTES
mlen = ffi.new("unsigned long long *")
message = ffi.new("unsigned char[]", mxout)
if aad:
_aad = aad
aalen = len(aad)
else:
_aad = ffi.NULL
aalen = 0
res = lib.crypto_aead_xchacha20poly1305_ietf_decrypt(message,
mlen,
ffi.NULL,
ciphertext,
clen,
_aad,
aalen,
nonce,
key)
ensure(res == 0, "Decryption failed.", raising=exc.CryptoError)
return ffi.buffer(message, mlen[0])[:]

View File

@@ -0,0 +1,313 @@
# 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 __future__ import absolute_import, division, print_function
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 = lib.crypto_box_secretkeybytes()
crypto_box_PUBLICKEYBYTES = lib.crypto_box_publickeybytes()
crypto_box_SEEDBYTES = lib.crypto_box_seedbytes()
crypto_box_NONCEBYTES = lib.crypto_box_noncebytes()
crypto_box_ZEROBYTES = lib.crypto_box_zerobytes()
crypto_box_BOXZEROBYTES = lib.crypto_box_boxzerobytes()
crypto_box_BEFORENMBYTES = lib.crypto_box_beforenmbytes()
crypto_box_SEALBYTES = lib.crypto_box_sealbytes()
def crypto_box_keypair():
"""
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):
"""
Returns a (public, secret) keypair deterministically generated
from an input ``seed``.
.. warning:: The seed **must** be high-entropy; therefore,
its generator **must** be a cryptographic quality
random function like, for example, :func:`~nacl.utils.random`.
.. warning:: The seed **must** be protected and remain secret.
Anyone who knows the seed is really in possession of
the corresponding PrivateKey.
:param seed: bytes
:rtype: (bytes(public_key), bytes(secret_key))
"""
ensure(isinstance(seed, bytes),
"seed must be bytes",
raising=TypeError)
if len(seed) != crypto_box_SEEDBYTES:
raise exc.ValueError("Invalid seed")
pk = ffi.new("unsigned char[]", crypto_box_PUBLICKEYBYTES)
sk = ffi.new("unsigned char[]", crypto_box_SECRETKEYBYTES)
rc = lib.crypto_box_seed_keypair(pk, sk, seed)
ensure(rc == 0,
'Unexpected library error',
raising=exc.RuntimeError)
return (
ffi.buffer(pk, crypto_box_PUBLICKEYBYTES)[:],
ffi.buffer(sk, crypto_box_SECRETKEYBYTES)[:],
)
def crypto_box(message, nonce, pk, sk):
"""
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, nonce, pk, sk):
"""
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, sk):
"""
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, nonce, k):
"""
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, nonce, k):
"""
Decrypts and returns the encrypted message ``ciphertext``, using the shared
key ``k`` and the nonce ``nonce``.
:param ciphertext: bytes
:param nonce: bytes
:param k: bytes
:rtype: bytes
"""
if len(nonce) != crypto_box_NONCEBYTES:
raise exc.ValueError("Invalid nonce")
if len(k) != crypto_box_BEFORENMBYTES:
raise exc.ValueError("Invalid shared key")
padded = (b"\x00" * crypto_box_BOXZEROBYTES) + ciphertext
plaintext = ffi.new("unsigned char[]", len(padded))
res = lib.crypto_box_open_afternm(
plaintext, padded, len(padded), nonce, k)
ensure(res == 0, "An error occurred trying to decrypt the message",
raising=exc.CryptoError)
return ffi.buffer(plaintext, len(padded))[crypto_box_ZEROBYTES:]
def crypto_box_seal(message, pk):
"""
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, pk, sk):
"""
Decrypts and returns an encrypted message ``ciphertext``, using the
recipent's secret key ``sk`` and the sender's ephemeral public key
embedded in the sealed box. The box contruct nonce is derived from
the recipient's public key ``pk`` and the sender's public key.
:param ciphertext: bytes
:param pk: bytes
:param sk: bytes
:rtype: bytes
.. versionadded:: 1.2
"""
ensure(isinstance(ciphertext, bytes),
"input ciphertext must be bytes",
raising=TypeError)
ensure(isinstance(pk, bytes),
"public key must be bytes",
raising=TypeError)
ensure(isinstance(sk, bytes),
"secret key must be bytes",
raising=TypeError)
if len(pk) != crypto_box_PUBLICKEYBYTES:
raise exc.ValueError("Invalid public key")
if len(sk) != crypto_box_SECRETKEYBYTES:
raise exc.ValueError("Invalid secret key")
_clen = len(ciphertext)
_mlen = _clen - crypto_box_SEALBYTES
plaintext = ffi.new("unsigned char[]", _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)[:]

View File

@@ -0,0 +1,216 @@
# 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 __future__ import absolute_import, division, print_function
from six import integer_types
from nacl import exceptions as exc
from nacl._sodium import ffi, lib
from nacl.exceptions import ensure
crypto_generichash_BYTES = lib.crypto_generichash_blake2b_bytes()
crypto_generichash_BYTES_MIN = lib.crypto_generichash_blake2b_bytes_min()
crypto_generichash_BYTES_MAX = lib.crypto_generichash_blake2b_bytes_max()
crypto_generichash_KEYBYTES = lib.crypto_generichash_blake2b_keybytes()
crypto_generichash_KEYBYTES_MIN = lib.crypto_generichash_blake2b_keybytes_min()
crypto_generichash_KEYBYTES_MAX = lib.crypto_generichash_blake2b_keybytes_max()
crypto_generichash_SALTBYTES = lib.crypto_generichash_blake2b_saltbytes()
crypto_generichash_PERSONALBYTES = \
lib.crypto_generichash_blake2b_personalbytes()
crypto_generichash_STATEBYTES = lib.crypto_generichash_statebytes()
_OVERLONG = '{0} length greater than {1} bytes'
_TOOBIG = '{0} greater than {1}'
def _checkparams(digest_size, key, salt, person):
"""Check hash paramters"""
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, integer_types),
'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,
digest_size=crypto_generichash_BYTES,
key=b'', salt=b'', person=b''):
"""One shot hash interface
:param data: the input data to the hash function
: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)[:]
def generichash_blake2b_init(key=b'', salt=b'',
person=b'',
digest_size=crypto_generichash_BYTES):
"""
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: an initizialized state buffer
:rtype: object
"""
_checkparams(digest_size, key, salt, person)
statebuf = ffi.new("unsigned char[]", crypto_generichash_STATEBYTES)
# 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(statebuf,
key, len(key),
digest_size,
_salt, _person)
ensure(rc == 0, 'Unexpected failure',
raising=exc.RuntimeError)
return statebuf
def generichash_blake2b_update(statebuf, data):
"""Update the blake2b hash state
:param statebuf: an initialized blake2b state buffer as returned from
:py:func:`.crypto_generichash_blake2b_init`
:type statebuf: object
:param data:
:type data: bytes
"""
ensure(isinstance(data, bytes),
'Input data must be a bytes sequence',
raising=exc.TypeError)
rc = lib.crypto_generichash_blake2b_update(statebuf, data, len(data))
ensure(rc == 0, 'Unexpected failure',
raising=exc.RuntimeError)
def generichash_blake2b_final(statebuf, digest_size):
"""Finalize the blake2b hash state and return the digest.
:param statebuf:
:type statebuf: object
:param digest_size:
:type digest_size: int
:return: the blake2 digest of the passed-in data stream
:rtype: bytes
"""
_digest = ffi.new("unsigned char[]", crypto_generichash_BYTES_MAX)
rc = lib.crypto_generichash_blake2b_final(statebuf, _digest, digest_size)
ensure(rc == 0, 'Unexpected failure',
raising=exc.RuntimeError)
return ffi.buffer(_digest, digest_size)[:]
def generichash_blake2b_state_copy(statebuf):
"""Return a copy of the given blake2b hash state"""
newstate = ffi.new("unsigned char[]", crypto_generichash_STATEBYTES)
ffi.memmove(newstate, statebuf, crypto_generichash_STATEBYTES)
return newstate

View File

@@ -0,0 +1,70 @@
# 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 __future__ import absolute_import, division, print_function
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 = lib.crypto_hash_sha512_bytes()
crypto_hash_sha256_BYTES = lib.crypto_hash_sha256_bytes()
crypto_hash_sha512_BYTES = lib.crypto_hash_sha512_bytes()
def crypto_hash(message):
"""
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):
"""
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):
"""
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)[:]

View File

@@ -0,0 +1,167 @@
# 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 __future__ import absolute_import, division, print_function
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 = lib.crypto_kx_publickeybytes()
crypto_kx_SECRET_KEY_BYTES = lib.crypto_kx_secretkeybytes()
crypto_kx_SEED_BYTES = lib.crypto_kx_seedbytes()
crypto_kx_SESSION_KEY_BYTES = lib.crypto_kx_sessionkeybytes()
def crypto_kx_keypair():
"""
Generate a keypair.
This is a duplicate crypto_box_keypair, but
is included for api consistency.
:return: (public_key, secret_key)
:rtype: (bytes, bytes)
"""
public_key = ffi.new("unsigned char[]", crypto_kx_PUBLIC_KEY_BYTES)
secret_key = ffi.new("unsigned char[]", crypto_kx_SECRET_KEY_BYTES)
res = lib.crypto_kx_keypair(public_key, secret_key)
ensure(res == 0, "Key generation failed.", raising=exc.CryptoError)
return (ffi.buffer(public_key, crypto_kx_PUBLIC_KEY_BYTES)[:],
ffi.buffer(secret_key, crypto_kx_SECRET_KEY_BYTES)[:])
def crypto_kx_seed_keypair(seed):
"""
Generate a keypair with a given seed.
This is functionally the same as crypto_box_seed_keypair, however
it uses the blake2b hash primitive instead of sha512.
It is included mainly for api consistency when using crypto_kx.
:param seed: random seed
:type seed: bytes
:return: (public_key, secret_key)
:rtype: (bytes, bytes)
"""
public_key = ffi.new("unsigned char[]", crypto_kx_PUBLIC_KEY_BYTES)
secret_key = ffi.new("unsigned char[]", crypto_kx_SECRET_KEY_BYTES)
ensure(isinstance(seed, bytes) and
len(seed) == crypto_kx_SEED_BYTES,
'Seed must be a {0} 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,
client_secret_key,
server_public_key):
"""
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 {0} 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 {0} 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 {0} 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,
server_secret_key,
client_public_key):
"""
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 {0} 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 {0} 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 {0} 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)[:])

View File

@@ -0,0 +1,470 @@
# 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 __future__ import absolute_import, division, print_function
import sys
from six import integer_types
import nacl.exceptions as exc
from nacl._sodium import ffi, lib
from nacl.exceptions import ensure
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 = lib.crypto_pwhash_alg_argon2i13()
crypto_pwhash_ALG_ARGON2ID13 = lib.crypto_pwhash_alg_argon2id13()
crypto_pwhash_ALG_DEFAULT = lib.crypto_pwhash_alg_default()
crypto_pwhash_SALTBYTES = lib.crypto_pwhash_saltbytes()
crypto_pwhash_STRBYTES = lib.crypto_pwhash_strbytes()
crypto_pwhash_PASSWD_MIN = lib.crypto_pwhash_passwd_min()
crypto_pwhash_PASSWD_MAX = lib.crypto_pwhash_passwd_max()
crypto_pwhash_BYTES_MIN = lib.crypto_pwhash_bytes_min()
crypto_pwhash_BYTES_MAX = lib.crypto_pwhash_bytes_max()
crypto_pwhash_argon2i_STRPREFIX = \
ffi.string(ffi.cast("char *",
lib.crypto_pwhash_argon2i_strprefix()
)
)[:]
crypto_pwhash_argon2i_MEMLIMIT_MIN = \
lib.crypto_pwhash_argon2i_memlimit_min()
crypto_pwhash_argon2i_MEMLIMIT_MAX = \
lib.crypto_pwhash_argon2i_memlimit_max()
crypto_pwhash_argon2i_OPSLIMIT_MIN = \
lib.crypto_pwhash_argon2i_opslimit_min()
crypto_pwhash_argon2i_OPSLIMIT_MAX = \
lib.crypto_pwhash_argon2i_opslimit_max()
crypto_pwhash_argon2i_OPSLIMIT_INTERACTIVE = \
lib.crypto_pwhash_argon2i_opslimit_interactive()
crypto_pwhash_argon2i_MEMLIMIT_INTERACTIVE = \
lib.crypto_pwhash_argon2i_memlimit_interactive()
crypto_pwhash_argon2i_OPSLIMIT_MODERATE = \
lib.crypto_pwhash_argon2i_opslimit_moderate()
crypto_pwhash_argon2i_MEMLIMIT_MODERATE = \
lib.crypto_pwhash_argon2i_memlimit_moderate()
crypto_pwhash_argon2i_OPSLIMIT_SENSITIVE = \
lib.crypto_pwhash_argon2i_opslimit_sensitive()
crypto_pwhash_argon2i_MEMLIMIT_SENSITIVE = \
lib.crypto_pwhash_argon2i_memlimit_sensitive()
crypto_pwhash_argon2id_STRPREFIX = \
ffi.string(ffi.cast("char *",
lib.crypto_pwhash_argon2id_strprefix()
)
)[:]
crypto_pwhash_argon2id_MEMLIMIT_MIN = \
lib.crypto_pwhash_argon2id_memlimit_min()
crypto_pwhash_argon2id_MEMLIMIT_MAX = \
lib.crypto_pwhash_argon2id_memlimit_max()
crypto_pwhash_argon2id_OPSLIMIT_MIN = \
lib.crypto_pwhash_argon2id_opslimit_min()
crypto_pwhash_argon2id_OPSLIMIT_MAX = \
lib.crypto_pwhash_argon2id_opslimit_max()
crypto_pwhash_argon2id_OPSLIMIT_INTERACTIVE = \
lib.crypto_pwhash_argon2id_opslimit_interactive()
crypto_pwhash_argon2id_MEMLIMIT_INTERACTIVE = \
lib.crypto_pwhash_argon2id_memlimit_interactive()
crypto_pwhash_argon2id_OPSLIMIT_MODERATE = \
lib.crypto_pwhash_argon2id_opslimit_moderate()
crypto_pwhash_argon2id_MEMLIMIT_MODERATE = \
lib.crypto_pwhash_argon2id_memlimit_moderate()
crypto_pwhash_argon2id_OPSLIMIT_SENSITIVE = \
lib.crypto_pwhash_argon2id_opslimit_sensitive()
crypto_pwhash_argon2id_MEMLIMIT_SENSITIVE = \
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, r, p, maxmem=SCRYPT_MAX_MEM):
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 {0}'.format(SCRYPT_PR_MAX),
raising=exc.ValueError)
ensure(n < (1 << (16 * r)),
raising=exc.ValueError)
Blen = p * 128 * r
i = UINT64_MAX / 128
ensure(n + 2 <= i / r,
raising=exc.ValueError)
Vlen = 32 * r * (n + 2) * 4
ensure(Blen <= UINT64_MAX - Vlen,
raising=exc.ValueError)
ensure(Blen <= sys.maxsize - Vlen,
raising=exc.ValueError)
ensure(Blen + Vlen <= maxmem,
'Memory limit would be exceeded with the choosen n, r, p',
raising=exc.ValueError)
def nacl_bindings_pick_scrypt_params(opslimit, memlimit):
"""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, salt, n, r, p, dklen=64,
maxmem=SCRYPT_MAX_MEM):
"""
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
"""
ensure(isinstance(n, integer_types),
raising=TypeError)
ensure(isinstance(r, integer_types),
raising=TypeError)
ensure(isinstance(p, integer_types),
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, opslimit=SCRYPT_OPSLIMIT_INTERACTIVE,
memlimit=SCRYPT_MEMLIMIT_INTERACTIVE):
"""
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
"""
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, passwd):
"""
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
"""
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, memlimit, alg):
if (alg == crypto_pwhash_ALG_ARGON2I13):
if memlimit < crypto_pwhash_argon2i_MEMLIMIT_MIN:
raise exc.ValueError('memlimit must be at least {0} bytes'.format(
crypto_pwhash_argon2i_MEMLIMIT_MIN))
elif memlimit > crypto_pwhash_argon2i_MEMLIMIT_MAX:
raise exc.ValueError('memlimit must be at most {0} bytes'.format(
crypto_pwhash_argon2i_MEMLIMIT_MAX))
if opslimit < crypto_pwhash_argon2i_OPSLIMIT_MIN:
raise exc.ValueError('opslimit must be at least {0}'.format(
crypto_pwhash_argon2i_OPSLIMIT_MIN))
elif opslimit > crypto_pwhash_argon2i_OPSLIMIT_MAX:
raise exc.ValueError('opslimit must be at most {0}'.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 {0} bytes'.format(
crypto_pwhash_argon2id_MEMLIMIT_MIN))
elif memlimit > crypto_pwhash_argon2id_MEMLIMIT_MAX:
raise exc.ValueError('memlimit must be at most {0} bytes'.format(
crypto_pwhash_argon2id_MEMLIMIT_MAX))
if opslimit < crypto_pwhash_argon2id_OPSLIMIT_MIN:
raise exc.ValueError('opslimit must be at least {0}'.format(
crypto_pwhash_argon2id_OPSLIMIT_MIN))
elif opslimit > crypto_pwhash_argon2id_OPSLIMIT_MAX:
raise exc.ValueError('opslimit must be at most {0}'.format(
crypto_pwhash_argon2id_OPSLIMIT_MAX))
else:
raise exc.TypeError('Unsupported algorithm')
def crypto_pwhash_alg(outlen, passwd, salt, opslimit, memlimit, alg):
"""
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 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, integer_types),
raising=exc.TypeError)
ensure(isinstance(opslimit, integer_types),
raising=exc.TypeError)
ensure(isinstance(memlimit, integer_types),
raising=exc.TypeError)
ensure(isinstance(alg, integer_types),
raising=exc.TypeError)
ensure(isinstance(passwd, bytes),
raising=exc.TypeError)
if len(salt) != crypto_pwhash_SALTBYTES:
raise exc.ValueError("salt must be exactly {0} bytes long".format(
crypto_pwhash_SALTBYTES))
if outlen < crypto_pwhash_BYTES_MIN:
raise exc.ValueError(
'derived key must be at least {0} bytes long'.format(
crypto_pwhash_BYTES_MIN))
elif outlen > crypto_pwhash_BYTES_MAX:
raise exc.ValueError(
'derived key must be at most {0} 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, opslimit, memlimit, alg):
"""
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, integer_types),
raising=TypeError)
ensure(isinstance(memlimit, integer_types),
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, passwd):
"""
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

View File

@@ -0,0 +1,60 @@
# 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 __future__ import absolute_import, division, print_function
from nacl import exceptions as exc
from nacl._sodium import ffi, lib
from nacl.exceptions import ensure
crypto_scalarmult_BYTES = lib.crypto_scalarmult_bytes()
crypto_scalarmult_SCALARBYTES = lib.crypto_scalarmult_scalarbytes()
def crypto_scalarmult_base(n):
"""
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, p):
"""
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)[:]

View File

@@ -0,0 +1,81 @@
# 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 __future__ import absolute_import, division, print_function
from nacl import exceptions as exc
from nacl._sodium import ffi, lib
from nacl.exceptions import ensure
crypto_secretbox_KEYBYTES = lib.crypto_secretbox_keybytes()
crypto_secretbox_NONCEBYTES = lib.crypto_secretbox_noncebytes()
crypto_secretbox_ZEROBYTES = lib.crypto_secretbox_zerobytes()
crypto_secretbox_BOXZEROBYTES = lib.crypto_secretbox_boxzerobytes()
crypto_secretbox_MACBYTES = lib.crypto_secretbox_macbytes()
crypto_secretbox_MESSAGEBYTES_MAX = lib.crypto_secretbox_messagebytes_max()
def crypto_secretbox(message, nonce, key):
"""
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, nonce, key):
"""
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:]

View File

@@ -0,0 +1,323 @@
# 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 __future__ import absolute_import, division, print_function
from nacl import exceptions as exc
from nacl._sodium import ffi, lib
from nacl.exceptions import ensure
crypto_secretstream_xchacha20poly1305_ABYTES = \
lib.crypto_secretstream_xchacha20poly1305_abytes()
crypto_secretstream_xchacha20poly1305_HEADERBYTES = \
lib.crypto_secretstream_xchacha20poly1305_headerbytes()
crypto_secretstream_xchacha20poly1305_KEYBYTES = \
lib.crypto_secretstream_xchacha20poly1305_keybytes()
crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX = \
lib.crypto_secretstream_xchacha20poly1305_messagebytes_max()
crypto_secretstream_xchacha20poly1305_STATEBYTES = \
lib.crypto_secretstream_xchacha20poly1305_statebytes()
crypto_secretstream_xchacha20poly1305_TAG_MESSAGE = \
lib.crypto_secretstream_xchacha20poly1305_tag_message()
crypto_secretstream_xchacha20poly1305_TAG_PUSH = \
lib.crypto_secretstream_xchacha20poly1305_tag_push()
crypto_secretstream_xchacha20poly1305_TAG_REKEY = \
lib.crypto_secretstream_xchacha20poly1305_tag_rekey()
crypto_secretstream_xchacha20poly1305_TAG_FINAL = \
lib.crypto_secretstream_xchacha20poly1305_tag_final()
def crypto_secretstream_xchacha20poly1305_keygen():
"""
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(object):
"""
An object wrapping the crypto_secretstream_xchacha20poly1305 state.
"""
__slots__ = ['statebuf', 'rawbuf', 'tagbuf']
def __init__(self):
""" Initialize a clean state object."""
self.statebuf = ffi.new(
"unsigned char[]",
crypto_secretstream_xchacha20poly1305_STATEBYTES,
)
self.rawbuf = None
self.tagbuf = None
def crypto_secretstream_xchacha20poly1305_init_push(state, key):
"""
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,
m,
ad=None,
tag=crypto_secretstream_xchacha20poly1305_TAG_MESSAGE,
):
"""
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, header, key):
"""
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, c, ad=None):
"""
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)
return (ffi.buffer(state.rawbuf, mlen)[:], int(state.tagbuf[0]))
def crypto_secretstream_xchacha20poly1305_rekey(state):
"""
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)

View File

@@ -0,0 +1,62 @@
# 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.
from __future__ import absolute_import, division, print_function
import nacl.exceptions as exc
from nacl._sodium import ffi, lib
from nacl.exceptions import ensure
BYTES = lib.crypto_shorthash_siphash24_bytes()
KEYBYTES = lib.crypto_shorthash_siphash24_keybytes()
XBYTES = lib.crypto_shorthash_siphashx24_bytes()
XKEYBYTES = lib.crypto_shorthash_siphashx24_keybytes()
def crypto_shorthash_siphash24(data, key):
"""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 {0} 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, key):
"""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
"""
if len(key) != XKEYBYTES:
raise exc.ValueError(
"Key length must be exactly {0} 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)[:]

View File

@@ -0,0 +1,285 @@
# 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 __future__ import absolute_import, division, print_function
from nacl import exceptions as exc
from nacl._sodium import ffi, lib
from nacl.exceptions import ensure
crypto_sign_BYTES = lib.crypto_sign_bytes()
# crypto_sign_SEEDBYTES = lib.crypto_sign_seedbytes()
crypto_sign_SEEDBYTES = lib.crypto_sign_secretkeybytes() // 2
crypto_sign_PUBLICKEYBYTES = lib.crypto_sign_publickeybytes()
crypto_sign_SECRETKEYBYTES = lib.crypto_sign_secretkeybytes()
crypto_sign_curve25519_BYTES = lib.crypto_box_secretkeybytes()
crypto_sign_ed25519ph_STATEBYTES = lib.crypto_sign_ed25519ph_statebytes()
def crypto_sign_keypair():
"""
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):
"""
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, sk):
"""
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, pk):
"""
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):
"""
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):
"""
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 public_key_bytes: bytes
:rtype: bytes
"""
if len(secret_key_bytes) != crypto_sign_SECRETKEYBYTES:
raise exc.ValueError("Invalid curve public 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)[:]
class crypto_sign_ed25519ph_state(object):
"""
State object wrapping the sha-512 state used in ed25519ph computation
"""
__slots__ = ['state']
def __init__(self):
self.state = 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, pmsg):
"""
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,
sk):
"""
Create a signature for the data hashed in edph
using the secret key sk
:param edph: the ed25519ph state for the data
being signed
:type edph: crypto_sign_ed25519ph_state
:param sk: the ed25519 secret part of the signing key
:type sk: bytes
:return: ed25519ph signature
:rtype: bytes
"""
ensure(isinstance(edph, crypto_sign_ed25519ph_state),
'edph parameter must be a ed25519ph_state object',
raising=exc.TypeError)
ensure(isinstance(sk, bytes),
'secret key parameter must be a bytes object',
raising=exc.TypeError)
ensure(len(sk) == crypto_sign_SECRETKEYBYTES,
('secret key must be {0} '
'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,
signature,
pk):
"""
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 {0} '
'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 {0} '
'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

View File

@@ -0,0 +1,30 @@
# 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 __future__ import absolute_import, division, print_function
from nacl._sodium import ffi, lib
def randombytes(size):
"""
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)[:]

View File

@@ -0,0 +1,32 @@
# 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 __future__ import absolute_import, division, print_function
from nacl import exceptions as exc
from nacl._sodium import ffi, lib
from nacl.exceptions import ensure
def _sodium_init():
ensure(lib.sodium_init() != -1,
"Could not initialize sodium",
raising=exc.RuntimeError)
def sodium_init():
"""
Initializes sodium, picking the best implementations available for this
machine.
"""
ffi.init_once(_sodium_init, "libsodium")

View File

@@ -0,0 +1,154 @@
# 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.
from __future__ import absolute_import, division, print_function
from six import integer_types
import nacl.exceptions as exc
from nacl._sodium import ffi, lib
from nacl.exceptions import ensure
def sodium_memcmp(inp1, inp2):
"""
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, blocksize):
"""
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, integer_types),
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, blocksize):
"""
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, integer_types),
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):
"""
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, b):
"""
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)[:]

View File

@@ -0,0 +1,90 @@
# 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 __future__ import absolute_import, division, print_function
import base64
import binascii
class RawEncoder(object):
@staticmethod
def encode(data):
return data
@staticmethod
def decode(data):
return data
class HexEncoder(object):
@staticmethod
def encode(data):
return binascii.hexlify(data)
@staticmethod
def decode(data):
return binascii.unhexlify(data)
class Base16Encoder(object):
@staticmethod
def encode(data):
return base64.b16encode(data)
@staticmethod
def decode(data):
return base64.b16decode(data)
class Base32Encoder(object):
@staticmethod
def encode(data):
return base64.b32encode(data)
@staticmethod
def decode(data):
return base64.b32decode(data)
class Base64Encoder(object):
@staticmethod
def encode(data):
return base64.b64encode(data)
@staticmethod
def decode(data):
return base64.b64decode(data)
class URLSafeBase64Encoder(object):
@staticmethod
def encode(data):
return base64.urlsafe_b64encode(data)
@staticmethod
def decode(data):
return base64.urlsafe_b64decode(data)
class Encodable(object):
def encode(self, encoder=RawEncoder):
return encoder.encode(bytes(self))

Binary file not shown.

View File

@@ -0,0 +1,68 @@
# 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 __future__ import absolute_import, division, print_function
class CryptoError(Exception):
"""
Base exception for all nacl related errors
"""
class BadSignatureError(CryptoError):
"""
Raised when the signature was forged or otherwise corrupt.
"""
class RuntimeError(RuntimeError, CryptoError):
pass
class AssertionError(AssertionError, CryptoError):
pass
class TypeError(TypeError, CryptoError):
pass
class ValueError(ValueError, CryptoError):
pass
class InvalidkeyError(CryptoError):
pass
def ensure(cond, *args, **kwds):
"""
Return if a condition is true, otherwise raise a caller-configurable
:py:class:`Exception`
:param bool cond: the condition to be checked
:param sequence args: the arguments to be passed to the exception's
constructor
The only accepted named parameter is `raising` used to configure the
exception to be raised if `cond` is not `True`
"""
_CHK_UNEXP = 'check_condition() got an unexpected keyword argument {0}'
raising = kwds.pop('raising', AssertionError)
if kwds:
raise TypeError(_CHK_UNEXP.format(repr(kwds.popitem()[0])))
if cond is True:
return
raise raising(*args)

Binary file not shown.

View File

@@ -0,0 +1,160 @@
# Copyright 2013 Donald Stufft and individual contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
The :mod:`nacl.hash` module exposes one-shot interfaces
for libsodium selected hash primitives and the constants needed
for their usage.
"""
from __future__ import absolute_import, division, print_function
import nacl.bindings
import nacl.encoding
BLAKE2B_BYTES = nacl.bindings.crypto_generichash_BYTES
"""Default digest size for :func:`blake2b` hash"""
BLAKE2B_BYTES_MIN = nacl.bindings.crypto_generichash_BYTES_MIN
"""Minimum allowed digest size for :func:`blake2b` hash"""
BLAKE2B_BYTES_MAX = nacl.bindings.crypto_generichash_BYTES_MAX
"""Maximum allowed digest size for :func:`blake2b` hash"""
BLAKE2B_KEYBYTES = nacl.bindings.crypto_generichash_KEYBYTES
"""Default size of the ``key`` byte array for :func:`blake2b` hash"""
BLAKE2B_KEYBYTES_MIN = nacl.bindings.crypto_generichash_KEYBYTES_MIN
"""Minimum allowed size of the ``key`` byte array for :func:`blake2b` hash"""
BLAKE2B_KEYBYTES_MAX = nacl.bindings.crypto_generichash_KEYBYTES_MAX
"""Maximum allowed size of the ``key`` byte array for :func:`blake2b` hash"""
BLAKE2B_SALTBYTES = nacl.bindings.crypto_generichash_SALTBYTES
"""Maximum allowed length of the ``salt`` byte array for
:func:`blake2b` hash"""
BLAKE2B_PERSONALBYTES = nacl.bindings.crypto_generichash_PERSONALBYTES
"""Maximum allowed length of the ``personalization``
byte array for :func:`blake2b` hash"""
SIPHASH_BYTES = nacl.bindings.crypto_shorthash_siphash24_BYTES
"""Size of the :func:`siphash24` digest"""
SIPHASH_KEYBYTES = nacl.bindings.crypto_shorthash_siphash24_KEYBYTES
"""Size of the secret ``key`` used by the :func:`siphash24` MAC"""
SIPHASHX_BYTES = nacl.bindings.crypto_shorthash_siphashx24_BYTES
"""Size of the :func:`siphashx24` digest"""
SIPHASHX_KEYBYTES = nacl.bindings.crypto_shorthash_siphashx24_KEYBYTES
"""Size of the secret ``key`` used by the :func:`siphashx24` MAC"""
_b2b_hash = nacl.bindings.crypto_generichash_blake2b_salt_personal
_sip_hash = nacl.bindings.crypto_shorthash_siphash24
_sip_hashx = nacl.bindings.crypto_shorthash_siphashx24
def sha256(message, encoder=nacl.encoding.HexEncoder):
"""
Hashes ``message`` with SHA256.
:param message: The message to hash.
:type message: bytes
:param encoder: A class that is able to encode the hashed message.
:returns: The hashed message.
:rtype: bytes
"""
return encoder.encode(nacl.bindings.crypto_hash_sha256(message))
def sha512(message, encoder=nacl.encoding.HexEncoder):
"""
Hashes ``message`` with SHA512.
:param message: The message to hash.
:type message: bytes
:param encoder: A class that is able to encode the hashed message.
:returns: The hashed message.
:rtype: bytes
"""
return encoder.encode(nacl.bindings.crypto_hash_sha512(message))
def blake2b(data, digest_size=BLAKE2B_BYTES, key=b'',
salt=b'', person=b'',
encoder=nacl.encoding.HexEncoder):
"""
Hashes ``data`` with blake2b.
:param data: the digest input byte sequence
:type data: bytes
:param digest_size: the requested digest size; must be at most
:const:`BLAKE2B_BYTES_MAX`;
the default digest size is
:const:`BLAKE2B_BYTES`
:type digest_size: int
:param key: the key to be set for keyed MAC/PRF usage; if set, the key
must be at most :data:`~nacl.hash.BLAKE2B_KEYBYTES_MAX` long
:type key: bytes
:param salt: an initialization salt at most
:const:`BLAKE2B_SALTBYTES` long;
it will be zero-padded if needed
:type salt: bytes
:param person: a personalization string at most
:const:`BLAKE2B_PERSONALBYTES` long;
it will be zero-padded if needed
:type person: bytes
:param encoder: the encoder to use on returned digest
:type encoder: class
:returns: The hashed message.
:rtype: bytes
"""
digest = _b2b_hash(data, digest_size=digest_size, key=key,
salt=salt, person=person)
return encoder.encode(digest)
generichash = blake2b
def siphash24(message, key=b'', encoder=nacl.encoding.HexEncoder):
"""
Computes a keyed MAC of ``message`` using the short-input-optimized
siphash-2-4 construction.
:param message: The message to hash.
:type message: bytes
:param key: the message authentication key for the siphash MAC construct
:type key: bytes(:const:`SIPHASH_KEYBYTES`)
:param encoder: A class that is able to encode the hashed message.
:returns: The hashed message.
:rtype: bytes(:const:`SIPHASH_BYTES`)
"""
digest = _sip_hash(message, key)
return encoder.encode(digest)
shorthash = siphash24
def siphashx24(message, key=b'', encoder=nacl.encoding.HexEncoder):
"""
Computes a keyed MAC of ``message`` using the 128 bit variant of the
siphash-2-4 construction.
:param message: The message to hash.
:type message: bytes
:param key: the message authentication key for the siphash MAC construct
:type key: bytes(:const:`SIPHASHX_KEYBYTES`)
:param encoder: A class that is able to encode the hashed message.
:returns: The hashed message.
:rtype: bytes(:const:`SIPHASHX_BYTES`)
.. versionadded:: 1.2
"""
digest = _sip_hashx(message, key)
return encoder.encode(digest)

Binary file not shown.

View File

@@ -0,0 +1,114 @@
# 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.
from __future__ import absolute_import, division, print_function
import binascii
import nacl.bindings
from nacl.utils import bytes_as_string
BYTES = nacl.bindings.crypto_generichash_BYTES
BYTES_MIN = nacl.bindings.crypto_generichash_BYTES_MIN
BYTES_MAX = nacl.bindings.crypto_generichash_BYTES_MAX
KEYBYTES = nacl.bindings.crypto_generichash_KEYBYTES
KEYBYTES_MIN = nacl.bindings.crypto_generichash_KEYBYTES_MIN
KEYBYTES_MAX = nacl.bindings.crypto_generichash_KEYBYTES_MAX
SALTBYTES = nacl.bindings.crypto_generichash_SALTBYTES
PERSONALBYTES = nacl.bindings.crypto_generichash_PERSONALBYTES
_b2b_init = nacl.bindings.crypto_generichash_blake2b_init
_b2b_final = nacl.bindings.crypto_generichash_blake2b_final
_b2b_copy = nacl.bindings.crypto_generichash_blake2b_state_copy
_b2b_update = nacl.bindings.crypto_generichash_blake2b_update
class blake2b(object):
"""
:py:mod:`hashlib` API compatible blake2b algorithm implementation
"""
MAX_DIGEST_SIZE = BYTES
MAX_KEY_SIZE = KEYBYTES_MAX
PERSON_SIZE = PERSONALBYTES
SALT_SIZE = SALTBYTES
def __init__(self, data=b'', digest_size=BYTES, key=b'',
salt=b'', person=b''):
"""
:py:class:`.blake2b` algorithm initializer
:param data:
:type data: bytes
:param int digest_size: the requested digest size; must be
at most :py:attr:`.MAX_DIGEST_SIZE`;
the default digest size is :py:data:`.BYTES`
:param key: the key to be set for keyed MAC/PRF usage; if set,
the key must be at most :py:data:`.KEYBYTES_MAX` long
:type key: bytes
:param salt: an initialization salt at most
:py:attr:`.SALT_SIZE` long; it will be zero-padded
if needed
:type salt: bytes
:param person: a personalization string at most
:py:attr:`.PERSONAL_SIZE` long; it will be zero-padded
if needed
:type person: bytes
"""
self._state = _b2b_init(key=key, salt=salt, person=person,
digest_size=digest_size)
self._digest_size = digest_size
if data:
self.update(data)
@property
def digest_size(self):
return self._digest_size
@property
def block_size(self):
return 128
@property
def name(self):
return 'blake2b'
def update(self, data):
_b2b_update(self._state, data)
def digest(self):
_st = nacl.bindings.crypto_generichash_blake2b_state_copy(self._state)
return _b2b_final(_st, self.digest_size)
def hexdigest(self):
return bytes_as_string(binascii.hexlify(self.digest()))
def copy(self):
_cp = type(self)(digest_size=self.digest_size)
_st = _b2b_copy(self._state)
_cp._state = _st
return _cp
def scrypt(password, salt='', n=2**20, r=8, p=1,
maxmem=2**25, dklen=64):
"""
Derive a cryptographic key using the scrypt KDF.
Implements the same signature as the ``hashlib.scrypt`` implemented
in cpython version 3.6
"""
return nacl.bindings.crypto_pwhash_scryptsalsa208sha256_ll(
password, salt, n, r, p, maxmem=maxmem, dklen=dklen)

Binary file not shown.

View File

@@ -0,0 +1,364 @@
# 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 __future__ import absolute_import, division, print_function
import nacl.bindings
from nacl import encoding
from nacl import exceptions as exc
from nacl.utils import EncryptedMessage, StringFixer, random
class PublicKey(encoding.Encodable, StringFixer, object):
"""
The public key counterpart to an Curve25519 :class:`nacl.public.PrivateKey`
for encrypting messages.
:param public_key: [:class:`bytes`] Encoded Curve25519 public key
:param encoder: A class that is able to decode the `public_key`
:cvar SIZE: The size that the public key is required to be
"""
SIZE = nacl.bindings.crypto_box_PUBLICKEYBYTES
def __init__(self, public_key, encoder=encoding.RawEncoder):
self._public_key = encoder.decode(public_key)
if not isinstance(self._public_key, bytes):
raise exc.TypeError("PublicKey must be created from 32 bytes")
if len(self._public_key) != self.SIZE:
raise exc.ValueError(
"The public key must be exactly {0} bytes long".format(
self.SIZE
)
)
def __bytes__(self):
return self._public_key
def __hash__(self):
return hash(bytes(self))
def __eq__(self, other):
if not isinstance(other, self.__class__):
return False
return nacl.bindings.sodium_memcmp(bytes(self), bytes(other))
def __ne__(self, other):
return not (self == other)
class PrivateKey(encoding.Encodable, StringFixer, object):
"""
Private key for decrypting messages using the Curve25519 algorithm.
.. warning:: This **must** be protected and remain secret. Anyone who
knows the value of your :class:`~nacl.public.PrivateKey` can decrypt
any message encrypted by the corresponding
:class:`~nacl.public.PublicKey`
:param private_key: The private key used to decrypt messages
:param encoder: The encoder class used to decode the given keys
:cvar SIZE: The size that the private key is required to be
:cvar SEED_SIZE: The size that the seed used to generate the
private key is required to be
"""
SIZE = nacl.bindings.crypto_box_SECRETKEYBYTES
SEED_SIZE = nacl.bindings.crypto_box_SEEDBYTES
def __init__(self, private_key, encoder=encoding.RawEncoder):
# Decode the secret_key
private_key = encoder.decode(private_key)
# verify the given secret key type and size are correct
if not (isinstance(private_key, bytes) and
len(private_key) == self.SIZE):
raise exc.TypeError(("PrivateKey must be created from a {0} "
"bytes long raw secret key").format(self.SIZE)
)
raw_public_key = nacl.bindings.crypto_scalarmult_base(private_key)
self._private_key = private_key
self.public_key = PublicKey(raw_public_key)
@classmethod
def from_seed(cls, seed, encoder=encoding.RawEncoder):
"""
Generate a PrivateKey using a deterministic construction
starting from a caller-provided seed
.. warning:: The seed **must** be high-entropy; therefore,
its generator **must** be a cryptographic quality
random function like, for example, :func:`~nacl.utils.random`.
.. warning:: The seed **must** be protected and remain secret.
Anyone who knows the seed is really in possession of
the corresponding PrivateKey.
:param seed: The seed used to generate the private key
:rtype: :class:`~nacl.public.PrivateKey`
"""
# decode the seed
seed = encoder.decode(seed)
# Verify the given seed type and size are correct
if not (isinstance(seed, bytes) and len(seed) == cls.SEED_SIZE):
raise exc.TypeError(("PrivateKey seed must be a {0} bytes long "
"binary sequence").format(cls.SEED_SIZE)
)
# generate a raw keypair from the given seed
raw_pk, raw_sk = nacl.bindings.crypto_box_seed_keypair(seed)
# construct a instance from the raw secret key
return cls(raw_sk)
def __bytes__(self):
return self._private_key
def __hash__(self):
return hash((type(self), bytes(self.public_key)))
def __eq__(self, other):
if not isinstance(other, self.__class__):
return False
return self.public_key == other.public_key
def __ne__(self, other):
return not (self == other)
@classmethod
def generate(cls):
"""
Generates a random :class:`~nacl.public.PrivateKey` object
:rtype: :class:`~nacl.public.PrivateKey`
"""
return cls(random(PrivateKey.SIZE), encoder=encoding.RawEncoder)
class Box(encoding.Encodable, StringFixer, object):
"""
The Box class boxes and unboxes messages between a pair of keys
The ciphertexts generated by :class:`~nacl.public.Box` include a 16
byte authenticator which is checked as part of the decryption. An invalid
authenticator will cause the decrypt function to raise an exception. The
authenticator is not a signature. Once you've decrypted the message you've
demonstrated the ability to create arbitrary valid message, so messages you
send are repudiable. For non-repudiable messages, sign them after
encryption.
:param private_key: :class:`~nacl.public.PrivateKey` used to encrypt and
decrypt messages
:param public_key: :class:`~nacl.public.PublicKey` used to encrypt and
decrypt messages
:cvar NONCE_SIZE: The size that the nonce is required to be.
"""
NONCE_SIZE = nacl.bindings.crypto_box_NONCEBYTES
def __init__(self, private_key, public_key):
if private_key and public_key:
if ((not isinstance(private_key, PrivateKey) or
not isinstance(public_key, PublicKey))):
raise exc.TypeError("Box must be created from "
"a PrivateKey and a PublicKey")
self._shared_key = nacl.bindings.crypto_box_beforenm(
public_key.encode(encoder=encoding.RawEncoder),
private_key.encode(encoder=encoding.RawEncoder),
)
else:
self._shared_key = None
def __bytes__(self):
return self._shared_key
@classmethod
def decode(cls, encoded, encoder=encoding.RawEncoder):
# Create an empty box
box = cls(None, None)
# Assign our decoded value to the shared key of the box
box._shared_key = encoder.decode(encoded)
return box
def encrypt(self, plaintext, nonce=None, encoder=encoding.RawEncoder):
"""
Encrypts the plaintext message using the given `nonce` (or generates
one randomly if omitted) and returns the ciphertext encoded with the
encoder.
.. warning:: It is **VITALLY** important that the nonce is a nonce,
i.e. it is a number used only once for any given key. If you fail
to do this, you compromise the privacy of the messages encrypted.
:param plaintext: [:class:`bytes`] The plaintext message to encrypt
:param nonce: [:class:`bytes`] The nonce to use in the encryption
:param encoder: The encoder to use to encode the ciphertext
:rtype: [:class:`nacl.utils.EncryptedMessage`]
"""
if nonce is None:
nonce = random(self.NONCE_SIZE)
if len(nonce) != self.NONCE_SIZE:
raise exc.ValueError("The nonce must be exactly %s bytes long" %
self.NONCE_SIZE)
ciphertext = nacl.bindings.crypto_box_afternm(
plaintext,
nonce,
self._shared_key,
)
encoded_nonce = encoder.encode(nonce)
encoded_ciphertext = encoder.encode(ciphertext)
return EncryptedMessage._from_parts(
encoded_nonce,
encoded_ciphertext,
encoder.encode(nonce + ciphertext),
)
def decrypt(self, ciphertext, nonce=None, encoder=encoding.RawEncoder):
"""
Decrypts the ciphertext using the `nonce` (explicitly, when passed as a
parameter or implicitly, when omitted, as part of the ciphertext) and
returns the plaintext message.
:param ciphertext: [:class:`bytes`] The encrypted message to decrypt
:param nonce: [:class:`bytes`] The nonce used when encrypting the
ciphertext
:param encoder: The encoder used to decode the ciphertext.
:rtype: [:class:`bytes`]
"""
# Decode our ciphertext
ciphertext = encoder.decode(ciphertext)
if nonce is None:
# If we were given the nonce and ciphertext combined, split them.
nonce = ciphertext[:self.NONCE_SIZE]
ciphertext = ciphertext[self.NONCE_SIZE:]
if len(nonce) != self.NONCE_SIZE:
raise exc.ValueError("The nonce must be exactly %s bytes long" %
self.NONCE_SIZE)
plaintext = nacl.bindings.crypto_box_open_afternm(
ciphertext,
nonce,
self._shared_key,
)
return plaintext
def shared_key(self):
"""
Returns the Curve25519 shared secret, that can then be used as a key in
other symmetric ciphers.
.. warning:: It is **VITALLY** important that you use a nonce with your
symmetric cipher. If you fail to do this, you compromise the
privacy of the messages encrypted. Ensure that the key length of
your cipher is 32 bytes.
:rtype: [:class:`bytes`]
"""
return self._shared_key
class SealedBox(encoding.Encodable, StringFixer, object):
"""
The SealedBox class boxes and unboxes messages addressed to
a specified key-pair by using ephemeral sender's keypairs,
whose private part will be discarded just after encrypting
a single plaintext message.
The ciphertexts generated by :class:`~nacl.public.SecretBox` include
the public part of the ephemeral key before the :class:`~nacl.public.Box`
ciphertext.
:param public_key: :class:`~nacl.public.PublicKey` used to encrypt
messages and derive nonces
:param private_key: :class:`~nacl.public.PrivateKey` used to decrypt
messages
.. versionadded:: 1.2
"""
def __init__(self, recipient_key):
if isinstance(recipient_key, PublicKey):
self._public_key = recipient_key.encode(
encoder=encoding.RawEncoder)
self._private_key = None
elif isinstance(recipient_key, PrivateKey):
self._private_key = recipient_key.encode(
encoder=encoding.RawEncoder)
self._public_key = recipient_key.public_key.encode(
encoder=encoding.RawEncoder)
else:
raise exc.TypeError("SealedBox must be created from "
"a PublicKey or a PrivateKey")
def __bytes__(self):
return self._public_key
def encrypt(self, plaintext, encoder=encoding.RawEncoder):
"""
Encrypts the plaintext message using a random-generated ephemeral
keypair and returns a "composed ciphertext", containing both
the public part of the keypair and the ciphertext proper,
encoded with the encoder.
The private part of the ephemeral key-pair will be scrubbed before
returning the ciphertext, therefore, the sender will not be able to
decrypt the generated ciphertext.
:param plaintext: [:class:`bytes`] The plaintext message to encrypt
:param encoder: The encoder to use to encode the ciphertext
:return bytes: encoded ciphertext
"""
ciphertext = nacl.bindings.crypto_box_seal(
plaintext,
self._public_key
)
encoded_ciphertext = encoder.encode(ciphertext)
return encoded_ciphertext
def decrypt(self, ciphertext, encoder=encoding.RawEncoder):
"""
Decrypts the ciphertext using the ephemeral public key enclosed
in the ciphertext and the SealedBox private key, returning
the plaintext message.
:param ciphertext: [:class:`bytes`] The encrypted message to decrypt
:param encoder: The encoder used to decode the ciphertext.
:return bytes: The original plaintext
"""
# Decode our ciphertext
ciphertext = encoder.decode(ciphertext)
plaintext = nacl.bindings.crypto_box_seal_open(
ciphertext,
self._public_key,
self._private_key,
)
return plaintext

Binary file not shown.

View File

@@ -0,0 +1,75 @@
# Copyright 2017 Donald Stufft and individual contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import
from nacl.exceptions import InvalidkeyError
from . import _argon2, argon2i, argon2id, scrypt
STRPREFIX = argon2id.STRPREFIX
PWHASH_SIZE = argon2id.PWHASH_SIZE
assert _argon2.ALG_ARGON2_DEFAULT == _argon2.ALG_ARGON2ID13
# since version 1.0.15 of libsodium
PASSWD_MIN = argon2id.PASSWD_MIN
PASSWD_MAX = argon2id.PASSWD_MAX
MEMLIMIT_MAX = argon2id.MEMLIMIT_MAX
MEMLIMIT_MIN = argon2id.MEMLIMIT_MIN
OPSLIMIT_MAX = argon2id.OPSLIMIT_MAX
OPSLIMIT_MIN = argon2id.OPSLIMIT_MIN
OPSLIMIT_INTERACTIVE = argon2id.OPSLIMIT_INTERACTIVE
MEMLIMIT_INTERACTIVE = argon2id.MEMLIMIT_INTERACTIVE
OPSLIMIT_MODERATE = argon2id.OPSLIMIT_MODERATE
MEMLIMIT_MODERATE = argon2id.MEMLIMIT_MODERATE
OPSLIMIT_SENSITIVE = argon2id.OPSLIMIT_SENSITIVE
MEMLIMIT_SENSITIVE = argon2id.MEMLIMIT_SENSITIVE
str = argon2id.str
assert argon2i.ALG != argon2id.ALG
SCRYPT_SALTBYTES = scrypt.SALTBYTES
SCRYPT_PWHASH_SIZE = scrypt.PWHASH_SIZE
SCRYPT_OPSLIMIT_INTERACTIVE = scrypt.OPSLIMIT_INTERACTIVE
SCRYPT_MEMLIMIT_INTERACTIVE = scrypt.MEMLIMIT_INTERACTIVE
SCRYPT_OPSLIMIT_SENSITIVE = scrypt.OPSLIMIT_SENSITIVE
SCRYPT_MEMLIMIT_SENSITIVE = scrypt.MEMLIMIT_SENSITIVE
kdf_scryptsalsa208sha256 = scrypt.kdf
scryptsalsa208sha256_str = scrypt.str
verify_scryptsalsa208sha256 = scrypt.verify
def verify(password_hash, password):
"""
Takes a modular crypt encoded stored password hash derived using one
of the algorithms supported by `libsodium` and checks if the user provided
password will hash to the same string when using the parameters saved
in the stored hash
"""
if password_hash.startswith(argon2id.STRPREFIX):
return argon2id.verify(password_hash, password)
elif password_hash.startswith(argon2i.STRPREFIX):
return argon2id.verify(password_hash, password)
elif password_hash.startswith(scrypt.STRPREFIX):
return scrypt.verify(password_hash, password)
else:
raise(InvalidkeyError("given password_hash is not "
"in a supported format"
)
)

View File

@@ -0,0 +1,52 @@
# 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 __future__ import absolute_import
from __future__ import division
import nacl.bindings
_argon2_strbytes_plus_one = nacl.bindings.crypto_pwhash_STRBYTES
PWHASH_SIZE = _argon2_strbytes_plus_one - 1
SALTBYTES = nacl.bindings.crypto_pwhash_SALTBYTES
PASSWD_MIN = nacl.bindings.crypto_pwhash_PASSWD_MIN
PASSWD_MAX = nacl.bindings.crypto_pwhash_PASSWD_MAX
PWHASH_SIZE = _argon2_strbytes_plus_one - 1
BYTES_MAX = nacl.bindings.crypto_pwhash_BYTES_MAX
BYTES_MIN = nacl.bindings.crypto_pwhash_BYTES_MIN
ALG_ARGON2I13 = nacl.bindings.crypto_pwhash_ALG_ARGON2I13
ALG_ARGON2ID13 = nacl.bindings.crypto_pwhash_ALG_ARGON2ID13
ALG_ARGON2_DEFAULT = nacl.bindings.crypto_pwhash_ALG_DEFAULT
def verify(password_hash, password):
"""
Takes a modular crypt encoded argon2i or argon2id stored password hash
and checks if the user provided password will hash to the same string
when using the stored parameters
:param password_hash: password hash serialized in modular crypt() format
:type password_hash: bytes
:param password: user provided password
:type password: bytes
:rtype: boolean
.. versionadded:: 1.2
"""
return nacl.bindings.crypto_pwhash_str_verify(password_hash,
password)

View File

@@ -0,0 +1,135 @@
# Copyright 2013 Donald Stufft and individual contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import
from __future__ import division
import nacl.bindings
import nacl.encoding
from . import _argon2
ALG = _argon2.ALG_ARGON2I13
STRPREFIX = nacl.bindings.crypto_pwhash_argon2i_STRPREFIX
SALTBYTES = _argon2.SALTBYTES
PASSWD_MIN = _argon2.PASSWD_MIN
PASSWD_MAX = _argon2.PASSWD_MAX
PWHASH_SIZE = _argon2.PWHASH_SIZE
BYTES_MIN = _argon2.BYTES_MIN
BYTES_MAX = _argon2.BYTES_MAX
verify = _argon2.verify
MEMLIMIT_MAX = nacl.bindings.crypto_pwhash_argon2i_MEMLIMIT_MAX
MEMLIMIT_MIN = nacl.bindings.crypto_pwhash_argon2i_MEMLIMIT_MIN
OPSLIMIT_MAX = nacl.bindings.crypto_pwhash_argon2i_OPSLIMIT_MAX
OPSLIMIT_MIN = nacl.bindings.crypto_pwhash_argon2i_OPSLIMIT_MIN
OPSLIMIT_INTERACTIVE = \
nacl.bindings.crypto_pwhash_argon2i_OPSLIMIT_INTERACTIVE
MEMLIMIT_INTERACTIVE = \
nacl.bindings.crypto_pwhash_argon2i_MEMLIMIT_INTERACTIVE
OPSLIMIT_SENSITIVE = \
nacl.bindings.crypto_pwhash_argon2i_OPSLIMIT_SENSITIVE
MEMLIMIT_SENSITIVE = \
nacl.bindings.crypto_pwhash_argon2i_MEMLIMIT_SENSITIVE
OPSLIMIT_MODERATE = \
nacl.bindings.crypto_pwhash_argon2i_OPSLIMIT_MODERATE
MEMLIMIT_MODERATE = \
nacl.bindings.crypto_pwhash_argon2i_MEMLIMIT_MODERATE
def kdf(size, password, salt,
opslimit=OPSLIMIT_SENSITIVE,
memlimit=MEMLIMIT_SENSITIVE,
encoder=nacl.encoding.RawEncoder):
"""
Derive a ``size`` bytes long key from a caller-supplied
``password`` and ``salt`` pair using the argon2i
memory-hard construct.
the enclosing module provides the constants
- :py:const:`.OPSLIMIT_INTERACTIVE`
- :py:const:`.MEMLIMIT_INTERACTIVE`
- :py:const:`.OPSLIMIT_MODERATE`
- :py:const:`.MEMLIMIT_MODERATE`
- :py:const:`.OPSLIMIT_SENSITIVE`
- :py:const:`.MEMLIMIT_SENSITIVE`
as a guidance for correct settings.
:param size: derived key size, must be between
:py:const:`.BYTES_MIN` and
:py:const:`.BYTES_MAX`
:type size: int
:param password: password used to seed the key derivation procedure;
it length must be between
:py:const:`.PASSWD_MIN` and
:py:const:`.PASSWD_MAX`
:type password: bytes
:param salt: **RANDOM** salt used in the key derivation procedure;
its length must be exactly :py:const:`.SALTBYTES`
:type salt: bytes
:param opslimit: the time component (operation count)
of the key derivation procedure's computational cost;
it must be between
:py:const:`.OPSLIMIT_MIN` and
:py:const:`.OPSLIMIT_MAX`
:type opslimit: int
:param memlimit: the memory occupation component
of the key derivation procedure's computational cost;
it must be between
:py:const:`.MEMLIMIT_MIN` and
:py:const:`.MEMLIMIT_MAX`
:type memlimit: int
:rtype: bytes
.. versionadded:: 1.2
"""
return encoder.encode(
nacl.bindings.crypto_pwhash_alg(size, password, salt,
opslimit, memlimit,
ALG)
)
def str(password,
opslimit=OPSLIMIT_INTERACTIVE,
memlimit=MEMLIMIT_INTERACTIVE):
"""
Hashes a password with a random salt, using the memory-hard
argon2i construct and returning an ascii string that has all
the needed info to check against a future password
The default settings for opslimit and memlimit are those deemed
correct for the interactive user login case.
:param bytes password:
:param int opslimit:
:param int memlimit:
:rtype: bytes
.. versionadded:: 1.2
"""
return nacl.bindings.crypto_pwhash_str_alg(password,
opslimit,
memlimit,
ALG)

View File

@@ -0,0 +1,134 @@
# 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 __future__ import absolute_import
from __future__ import division
import nacl.bindings
import nacl.encoding
from . import _argon2
ALG = _argon2.ALG_ARGON2ID13
STRPREFIX = nacl.bindings.crypto_pwhash_argon2id_STRPREFIX
SALTBYTES = _argon2.SALTBYTES
PASSWD_MIN = _argon2.PASSWD_MIN
PASSWD_MAX = _argon2.PASSWD_MAX
PWHASH_SIZE = _argon2.PWHASH_SIZE
BYTES_MIN = _argon2.BYTES_MIN
BYTES_MAX = _argon2.BYTES_MAX
verify = _argon2.verify
MEMLIMIT_MIN = nacl.bindings.crypto_pwhash_argon2id_MEMLIMIT_MIN
MEMLIMIT_MAX = nacl.bindings.crypto_pwhash_argon2id_MEMLIMIT_MAX
OPSLIMIT_MIN = nacl.bindings.crypto_pwhash_argon2id_OPSLIMIT_MIN
OPSLIMIT_MAX = nacl.bindings.crypto_pwhash_argon2id_OPSLIMIT_MAX
OPSLIMIT_INTERACTIVE = \
nacl.bindings.crypto_pwhash_argon2id_OPSLIMIT_INTERACTIVE
MEMLIMIT_INTERACTIVE = \
nacl.bindings.crypto_pwhash_argon2id_MEMLIMIT_INTERACTIVE
OPSLIMIT_SENSITIVE = \
nacl.bindings.crypto_pwhash_argon2id_OPSLIMIT_SENSITIVE
MEMLIMIT_SENSITIVE = \
nacl.bindings.crypto_pwhash_argon2id_MEMLIMIT_SENSITIVE
OPSLIMIT_MODERATE = \
nacl.bindings.crypto_pwhash_argon2id_OPSLIMIT_MODERATE
MEMLIMIT_MODERATE = \
nacl.bindings.crypto_pwhash_argon2id_MEMLIMIT_MODERATE
def kdf(size, password, salt,
opslimit=OPSLIMIT_SENSITIVE,
memlimit=MEMLIMIT_SENSITIVE,
encoder=nacl.encoding.RawEncoder):
"""
Derive a ``size`` bytes long key from a caller-supplied
``password`` and ``salt`` pair using the argon2i
memory-hard construct.
the enclosing module provides the constants
- :py:const:`.OPSLIMIT_INTERACTIVE`
- :py:const:`.MEMLIMIT_INTERACTIVE`
- :py:const:`.OPSLIMIT_MODERATE`
- :py:const:`.MEMLIMIT_MODERATE`
- :py:const:`.OPSLIMIT_SENSITIVE`
- :py:const:`.MEMLIMIT_SENSITIVE`
as a guidance for correct settings.
:param size: derived key size, must be between
:py:const:`.BYTES_MIN` and
:py:const:`.BYTES_MAX`
:type size: int
:param password: password used to seed the key derivation procedure;
it length must be between
:py:const:`.PASSWD_MIN` and
:py:const:`.PASSWD_MAX`
:type password: bytes
:param salt: **RANDOM** salt used in the key derivation procedure;
its length must be exactly :py:const:`.SALTBYTES`
:type salt: bytes
:param opslimit: the time component (operation count)
of the key derivation procedure's computational cost;
it must be between
:py:const:`.OPSLIMIT_MIN` and
:py:const:`.OPSLIMIT_MAX`
:type opslimit: int
:param memlimit: the memory occupation component
of the key derivation procedure's computational cost;
it must be between
:py:const:`.MEMLIMIT_MIN` and
:py:const:`.MEMLIMIT_MAX`
:type memlimit: int
:rtype: bytes
.. versionadded:: 1.2
"""
return encoder.encode(
nacl.bindings.crypto_pwhash_alg(size, password, salt,
opslimit, memlimit,
ALG)
)
def str(password,
opslimit=OPSLIMIT_INTERACTIVE,
memlimit=MEMLIMIT_INTERACTIVE):
"""
Hashes a password with a random salt, using the memory-hard
argon2id construct and returning an ascii string that has all
the needed info to check against a future password
The default settings for opslimit and memlimit are those deemed
correct for the interactive user login case.
:param bytes password:
:param int opslimit:
:param int memlimit:
:rtype: bytes
.. versionadded:: 1.2
"""
return nacl.bindings.crypto_pwhash_str_alg(password,
opslimit,
memlimit,
ALG)

View File

@@ -0,0 +1,167 @@
# 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 __future__ import absolute_import
from __future__ import division
import nacl.bindings
import nacl.encoding
from nacl import exceptions as exc
from nacl.exceptions import ensure
_strbytes_plus_one = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_STRBYTES
STRPREFIX = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_STRPREFIX
SALTBYTES = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_SALTBYTES
PASSWD_MIN = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN
PASSWD_MAX = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX
PWHASH_SIZE = _strbytes_plus_one - 1
BYTES_MIN = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_BYTES_MIN
BYTES_MAX = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_BYTES_MAX
MEMLIMIT_MIN = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN
MEMLIMIT_MAX = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX
OPSLIMIT_MIN = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN
OPSLIMIT_MAX = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX
OPSLIMIT_INTERACTIVE = \
nacl.bindings.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE
MEMLIMIT_INTERACTIVE = \
nacl.bindings.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE
OPSLIMIT_SENSITIVE = \
nacl.bindings.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE
MEMLIMIT_SENSITIVE = \
nacl.bindings.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE
OPSLIMIT_MODERATE = 8 * OPSLIMIT_INTERACTIVE
MEMLIMIT_MODERATE = 8 * MEMLIMIT_INTERACTIVE
def kdf(size, password, salt,
opslimit=OPSLIMIT_SENSITIVE,
memlimit=MEMLIMIT_SENSITIVE,
encoder=nacl.encoding.RawEncoder):
"""
Derive a ``size`` bytes long key from a caller-supplied
``password`` and ``salt`` pair using the scryptsalsa208sha256
memory-hard construct.
the enclosing module provides the constants
- :py:const:`.OPSLIMIT_INTERACTIVE`
- :py:const:`.MEMLIMIT_INTERACTIVE`
- :py:const:`.OPSLIMIT_SENSITIVE`
- :py:const:`.MEMLIMIT_SENSITIVE`
- :py:const:`.OPSLIMIT_MODERATE`
- :py:const:`.MEMLIMIT_MODERATE`
as a guidance for correct settings respectively for the
interactive login and the long term key protecting sensitive data
use cases.
:param size: derived key size, must be between
:py:const:`.BYTES_MIN` and
:py:const:`.BYTES_MAX`
:type size: int
:param password: password used to seed the key derivation procedure;
it length must be between
:py:const:`.PASSWD_MIN` and
:py:const:`.PASSWD_MAX`
:type password: bytes
:param salt: **RANDOM** salt used in the key derivation procedure;
its length must be exactly :py:const:`.SALTBYTES`
:type salt: bytes
:param opslimit: the time component (operation count)
of the key derivation procedure's computational cost;
it must be between
:py:const:`.OPSLIMIT_MIN` and
:py:const:`.OPSLIMIT_MAX`
:type opslimit: int
:param memlimit: the memory occupation component
of the key derivation procedure's computational cost;
it must be between
:py:const:`.MEMLIMIT_MIN` and
:py:const:`.MEMLIMIT_MAX`
:type memlimit: int
:rtype: bytes
.. versionadded:: 1.2
"""
ensure(
len(salt) == SALTBYTES,
"The salt must be exactly %s, not %s bytes long" % (
SALTBYTES,
len(salt)
),
raising=exc.ValueError
)
n_log2, r, p = nacl.bindings.nacl_bindings_pick_scrypt_params(opslimit,
memlimit)
maxmem = memlimit + (2 ** 16)
return encoder.encode(
nacl.bindings.crypto_pwhash_scryptsalsa208sha256_ll(
password, salt, 2 ** n_log2, r, p, maxmem=maxmem, dklen=size)
)
def str(password,
opslimit=OPSLIMIT_INTERACTIVE,
memlimit=MEMLIMIT_INTERACTIVE):
"""
Hashes a password with a random salt, using the memory-hard
scryptsalsa208sha256 construct and returning an ascii string
that has all the needed info to check against a future password
The default settings for opslimit and memlimit are those deemed
correct for the interactive user login case.
:param bytes password:
:param int opslimit:
:param int memlimit:
:rtype: bytes
.. versionadded:: 1.2
"""
return nacl.bindings.crypto_pwhash_scryptsalsa208sha256_str(password,
opslimit,
memlimit)
def verify(password_hash, password):
"""
Takes the output of scryptsalsa208sha256 and compares it against
a user provided password to see if they are the same
:param password_hash: bytes
:param password: bytes
:rtype: boolean
.. versionadded:: 1.2
"""
ensure(len(password_hash) == PWHASH_SIZE,
"The password hash must be exactly %s bytes long" %
nacl.bindings.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
raising=exc.ValueError)
return nacl.bindings.crypto_pwhash_scryptsalsa208sha256_str_verify(
password_hash, password
)

Binary file not shown.

View File

@@ -0,0 +1,133 @@
# 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 __future__ import absolute_import, division, print_function
import nacl.bindings
from nacl import encoding
from nacl import exceptions as exc
from nacl.utils import EncryptedMessage, StringFixer, random
class SecretBox(encoding.Encodable, StringFixer, object):
"""
The SecretBox class encrypts and decrypts messages using the given secret
key.
The ciphertexts generated by :class:`~nacl.secret.Secretbox` include a 16
byte authenticator which is checked as part of the decryption. An invalid
authenticator will cause the decrypt function to raise an exception. The
authenticator is not a signature. Once you've decrypted the message you've
demonstrated the ability to create arbitrary valid message, so messages you
send are repudiable. For non-repudiable messages, sign them after
encryption.
:param key: The secret key used to encrypt and decrypt messages
:param encoder: The encoder class used to decode the given key
:cvar KEY_SIZE: The size that the key is required to be.
:cvar NONCE_SIZE: The size that the nonce is required to be.
:cvar MACBYTES: The size of the authentication MAC tag in bytes.
:cvar MESSAGEBYTES_MAX: The maximum size of a message which can be
safely encrypted with a single key/nonce
pair.
"""
KEY_SIZE = nacl.bindings.crypto_secretbox_KEYBYTES
NONCE_SIZE = nacl.bindings.crypto_secretbox_NONCEBYTES
MACBYTES = nacl.bindings.crypto_secretbox_MACBYTES
MESSAGEBYTES_MAX = nacl.bindings.crypto_secretbox_MESSAGEBYTES_MAX
def __init__(self, key, encoder=encoding.RawEncoder):
key = encoder.decode(key)
if not isinstance(key, bytes):
raise exc.TypeError("SecretBox must be created from 32 bytes")
if len(key) != self.KEY_SIZE:
raise exc.ValueError(
"The key must be exactly %s bytes long" %
self.KEY_SIZE,
)
self._key = key
def __bytes__(self):
return self._key
def encrypt(self, plaintext, nonce=None, encoder=encoding.RawEncoder):
"""
Encrypts the plaintext message using the given `nonce` (or generates
one randomly if omitted) and returns the ciphertext encoded with the
encoder.
.. warning:: It is **VITALLY** important that the nonce is a nonce,
i.e. it is a number used only once for any given key. If you fail
to do this, you compromise the privacy of the messages encrypted.
Give your nonces a different prefix, or have one side use an odd
counter and one an even counter. Just make sure they are different.
:param plaintext: [:class:`bytes`] The plaintext message to encrypt
:param nonce: [:class:`bytes`] The nonce to use in the encryption
:param encoder: The encoder to use to encode the ciphertext
:rtype: [:class:`nacl.utils.EncryptedMessage`]
"""
if nonce is None:
nonce = random(self.NONCE_SIZE)
if len(nonce) != self.NONCE_SIZE:
raise exc.ValueError(
"The nonce must be exactly %s bytes long" % self.NONCE_SIZE,
)
ciphertext = nacl.bindings.crypto_secretbox(plaintext,
nonce, self._key)
encoded_nonce = encoder.encode(nonce)
encoded_ciphertext = encoder.encode(ciphertext)
return EncryptedMessage._from_parts(
encoded_nonce,
encoded_ciphertext,
encoder.encode(nonce + ciphertext),
)
def decrypt(self, ciphertext, nonce=None, encoder=encoding.RawEncoder):
"""
Decrypts the ciphertext using the `nonce` (explicitly, when passed as a
parameter or implicitly, when omitted, as part of the ciphertext) and
returns the plaintext message.
:param ciphertext: [:class:`bytes`] The encrypted message to decrypt
:param nonce: [:class:`bytes`] The nonce used when encrypting the
ciphertext
:param encoder: The encoder used to decode the ciphertext.
:rtype: [:class:`bytes`]
"""
# Decode our ciphertext
ciphertext = encoder.decode(ciphertext)
if nonce is None:
# If we were given the nonce and ciphertext combined, split them.
nonce = ciphertext[:self.NONCE_SIZE]
ciphertext = ciphertext[self.NONCE_SIZE:]
if len(nonce) != self.NONCE_SIZE:
raise exc.ValueError(
"The nonce must be exactly %s bytes long" % self.NONCE_SIZE,
)
plaintext = nacl.bindings.crypto_secretbox_open(ciphertext,
nonce, self._key)
return plaintext

Binary file not shown.

View File

@@ -0,0 +1,216 @@
# 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 __future__ import absolute_import, division, print_function
import nacl.bindings
from nacl import encoding
from nacl import exceptions as exc
from nacl.public import (PrivateKey as _Curve25519_PrivateKey,
PublicKey as _Curve25519_PublicKey)
from nacl.utils import StringFixer, random
class SignedMessage(bytes):
"""
A bytes subclass that holds a messaged that has been signed by a
:class:`SigningKey`.
"""
@classmethod
def _from_parts(cls, signature, message, combined):
obj = cls(combined)
obj._signature = signature
obj._message = message
return obj
@property
def signature(self):
"""
The signature contained within the :class:`SignedMessage`.
"""
return self._signature
@property
def message(self):
"""
The message contained within the :class:`SignedMessage`.
"""
return self._message
class VerifyKey(encoding.Encodable, StringFixer, object):
"""
The public key counterpart to an Ed25519 SigningKey for producing digital
signatures.
:param key: [:class:`bytes`] Serialized Ed25519 public key
:param encoder: A class that is able to decode the `key`
"""
def __init__(self, key, encoder=encoding.RawEncoder):
# Decode the key
key = encoder.decode(key)
if not isinstance(key, bytes):
raise exc.TypeError("VerifyKey must be created from 32 bytes")
if len(key) != nacl.bindings.crypto_sign_PUBLICKEYBYTES:
raise exc.ValueError(
"The key must be exactly %s bytes long" %
nacl.bindings.crypto_sign_PUBLICKEYBYTES,
)
self._key = key
def __bytes__(self):
return self._key
def __hash__(self):
return hash(bytes(self))
def __eq__(self, other):
if not isinstance(other, self.__class__):
return False
return nacl.bindings.sodium_memcmp(bytes(self), bytes(other))
def __ne__(self, other):
return not (self == other)
def verify(self, smessage, signature=None, encoder=encoding.RawEncoder):
"""
Verifies the signature of a signed message, returning the message
if it has not been tampered with else raising
:class:`~nacl.signing.BadSignatureError`.
:param smessage: [:class:`bytes`] Either the original messaged or a
signature and message concated together.
:param signature: [:class:`bytes`] If an unsigned message is given for
smessage then the detached signature must be provided.
:param encoder: A class that is able to decode the secret message and
signature.
:rtype: :class:`bytes`
"""
if signature is not None:
# If we were given the message and signature separately, combine
# them.
smessage = signature + smessage
# Decode the signed message
smessage = encoder.decode(smessage)
return nacl.bindings.crypto_sign_open(smessage, self._key)
def to_curve25519_public_key(self):
"""
Converts a :class:`~nacl.signing.VerifyKey` to a
:class:`~nacl.public.PublicKey`
:rtype: :class:`~nacl.public.PublicKey`
"""
raw_pk = nacl.bindings.crypto_sign_ed25519_pk_to_curve25519(self._key)
return _Curve25519_PublicKey(raw_pk)
class SigningKey(encoding.Encodable, StringFixer, object):
"""
Private key for producing digital signatures using the Ed25519 algorithm.
Signing keys are produced from a 32-byte (256-bit) random seed value. This
value can be passed into the :class:`~nacl.signing.SigningKey` as a
:func:`bytes` whose length is 32.
.. warning:: This **must** be protected and remain secret. Anyone who knows
the value of your :class:`~nacl.signing.SigningKey` or it's seed can
masquerade as you.
:param seed: [:class:`bytes`] Random 32-byte value (i.e. private key)
:param encoder: A class that is able to decode the seed
:ivar: verify_key: [:class:`~nacl.signing.VerifyKey`] The verify
(i.e. public) key that corresponds with this signing key.
"""
def __init__(self, seed, encoder=encoding.RawEncoder):
# Decode the seed
seed = encoder.decode(seed)
if not isinstance(seed, bytes):
raise exc.TypeError(
"SigningKey must be created from a 32 byte seed")
# Verify that our seed is the proper size
if len(seed) != nacl.bindings.crypto_sign_SEEDBYTES:
raise exc.ValueError(
"The seed must be exactly %d bytes long" %
nacl.bindings.crypto_sign_SEEDBYTES
)
public_key, secret_key = nacl.bindings.crypto_sign_seed_keypair(seed)
self._seed = seed
self._signing_key = secret_key
self.verify_key = VerifyKey(public_key)
def __bytes__(self):
return self._seed
def __hash__(self):
return hash(bytes(self))
def __eq__(self, other):
if not isinstance(other, self.__class__):
return False
return nacl.bindings.sodium_memcmp(bytes(self), bytes(other))
def __ne__(self, other):
return not (self == other)
@classmethod
def generate(cls):
"""
Generates a random :class:`~nacl.signing.SigningKey` object.
:rtype: :class:`~nacl.signing.SigningKey`
"""
return cls(
random(nacl.bindings.crypto_sign_SEEDBYTES),
encoder=encoding.RawEncoder,
)
def sign(self, message, encoder=encoding.RawEncoder):
"""
Sign a message using this key.
:param message: [:class:`bytes`] The data to be signed.
:param encoder: A class that is used to encode the signed message.
:rtype: :class:`~nacl.signing.SignedMessage`
"""
raw_signed = nacl.bindings.crypto_sign(message, self._signing_key)
crypto_sign_BYTES = nacl.bindings.crypto_sign_BYTES
signature = encoder.encode(raw_signed[:crypto_sign_BYTES])
message = encoder.encode(raw_signed[crypto_sign_BYTES:])
signed = encoder.encode(raw_signed)
return SignedMessage._from_parts(signature, message, signed)
def to_curve25519_private_key(self):
"""
Converts a :class:`~nacl.signing.SigningKey` to a
:class:`~nacl.public.PrivateKey`
:rtype: :class:`~nacl.public.PrivateKey`
"""
sk = self._signing_key
raw_private = nacl.bindings.crypto_sign_ed25519_sk_to_curve25519(sk)
return _Curve25519_PrivateKey(raw_private)

Binary file not shown.

View File

@@ -0,0 +1,67 @@
# 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 __future__ import absolute_import, division, print_function
import os
import six
class EncryptedMessage(bytes):
"""
A bytes subclass that holds a messaged that has been encrypted by a
:class:`SecretBox`.
"""
@classmethod
def _from_parts(cls, nonce, ciphertext, combined):
obj = cls(combined)
obj._nonce = nonce
obj._ciphertext = ciphertext
return obj
@property
def nonce(self):
"""
The nonce used during the encryption of the :class:`EncryptedMessage`.
"""
return self._nonce
@property
def ciphertext(self):
"""
The ciphertext contained within the :class:`EncryptedMessage`.
"""
return self._ciphertext
class StringFixer(object):
def __str__(self):
if six.PY3:
return str(self.__bytes__())
else:
return self.__bytes__()
def bytes_as_string(bytes_in):
if six.PY3:
return bytes_in.decode('ascii')
else:
return bytes_in
def random(size=32):
return os.urandom(size)

Binary file not shown.