Source code for nacl.hashlib

# Copyright 2016-2019 Donald Stufft and individual contributors
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# See the License for the specific language governing permissions and
# limitations under the License.

import binascii
from typing import NoReturn

import nacl.bindings
from nacl.utils import bytes_as_string

BYTES = nacl.bindings.crypto_generichash_BYTES
BYTES_MIN = nacl.bindings.crypto_generichash_BYTES_MIN
BYTES_MAX = nacl.bindings.crypto_generichash_BYTES_MAX
KEYBYTES = nacl.bindings.crypto_generichash_KEYBYTES
KEYBYTES_MIN = nacl.bindings.crypto_generichash_KEYBYTES_MIN
KEYBYTES_MAX = nacl.bindings.crypto_generichash_KEYBYTES_MAX
SALTBYTES = nacl.bindings.crypto_generichash_SALTBYTES
PERSONALBYTES = nacl.bindings.crypto_generichash_PERSONALBYTES

SCRYPT_AVAILABLE = nacl.bindings.has_crypto_pwhash_scryptsalsa208sha256

_b2b_init = nacl.bindings.crypto_generichash_blake2b_init
_b2b_final = nacl.bindings.crypto_generichash_blake2b_final
_b2b_update = nacl.bindings.crypto_generichash_blake2b_update

[docs]class blake2b: """ :py:mod:`hashlib` API compatible blake2b algorithm implementation """ MAX_DIGEST_SIZE = BYTES MAX_KEY_SIZE = KEYBYTES_MAX PERSON_SIZE = PERSONALBYTES SALT_SIZE = SALTBYTES def __init__( self, data: bytes = b"", digest_size: int = BYTES, key: bytes = b"", salt: bytes = b"", person: bytes = b"", ): """ :py:class:`.blake2b` algorithm initializer :param data: :type data: bytes :param int digest_size: the requested digest size; must be at most :py:attr:`.MAX_DIGEST_SIZE`; the default digest size is :py:data:`.BYTES` :param key: the key to be set for keyed MAC/PRF usage; if set, the key must be at most :py:data:`.KEYBYTES_MAX` long :type key: bytes :param salt: a initialization salt at most :py:attr:`.SALT_SIZE` long; it will be zero-padded if needed :type salt: bytes :param person: a personalization string at most :py:attr:`.PERSONAL_SIZE` long; it will be zero-padded if needed :type person: bytes """ self._state = _b2b_init( key=key, salt=salt, person=person, digest_size=digest_size ) self._digest_size = digest_size if data: self.update(data) @property def digest_size(self) -> int: return self._digest_size @property def block_size(self) -> int: return 128 @property def name(self) -> str: return "blake2b" def update(self, data: bytes) -> None: _b2b_update(self._state, data) def digest(self) -> bytes: _st = self._state.copy() return _b2b_final(_st) def hexdigest(self) -> str: return bytes_as_string(binascii.hexlify(self.digest())) def copy(self) -> "blake2b": _cp = type(self)(digest_size=self.digest_size) _st = self._state.copy() _cp._state = _st return _cp def __reduce__(self) -> NoReturn: """ Raise the same exception as hashlib's blake implementation on copy.copy() """ raise TypeError( "can't pickle {} objects".format(self.__class__.__name__) )
[docs]def scrypt( password: bytes, salt: bytes = b"", n: int = 2**20, r: int = 8, p: int = 1, maxmem: int = 2**25, dklen: int = 64, ) -> bytes: """ Derive a cryptographic key using the scrypt KDF. :raises nacl.exceptions.UnavailableError: If called when using a minimal build of libsodium. Implements the same signature as the ``hashlib.scrypt`` implemented in cpython version 3.6 """ return nacl.bindings.crypto_pwhash_scryptsalsa208sha256_ll( password, salt, n, r, p, maxmem=maxmem, dklen=dklen )