Skip to content

Hashers

Note

If you need to use blake3 for something, import it from this module instead of doing so directly!
from blake2signer.hashers import blake3
This is because the package is optional, and it may not be installed: this module handles it properly, and will raise an exception when the function is called without the package installed, but not before.

blake2signer.hashers

Hashers handlers.

These are not meant to be used directly, but otherwise through a signer.

BLAKE2Hasher(hasher, *, secrets, digest_size, person)

Bases: BLAKEHasher

Hasher interface with BLAKE2.

BLAKE hasher to interface with different BLAKE versions.

Parameters:

Name Type Description Default
hasher HasherChoice

Hash function to use.

required

Other Parameters:

Name Type Description
secrets Tuple[bytes, ...]

A tuple of secret values which are derived using BLAKE to produce the signing key, to ensure they fit the hasher limits (so they have no practical size limit), from oldest to newest. This allows secret rotation: signatures are checked against all of them, but the last one (the newest one) is used to sign.

digest_size int

Size of digest in bytes.

person bytes

Personalisation string to force the hash function to produce different digests for the same input. It is derived using BLAKE to ensure it fits the hasher limits, so it has no practical size limit.

Raises:

Type Description
InvalidOptionError

A parameter is out of bounds.

Source code in blake2signer/hashers/blakehashers.py
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
def __init__(
    self,
    hasher: HasherChoice,
    *,
    secrets: typing.Tuple[bytes, ...],
    digest_size: int,
    person: bytes,
) -> None:
    """BLAKE hasher to interface with different BLAKE versions.

    Args:
        hasher: Hash function to use.

    Keyword Args:
        secrets: A tuple of secret values which are derived using BLAKE to produce
            the signing key, to ensure they fit the hasher limits (so they have
            no practical size limit), from oldest to newest. This allows secret
            rotation: signatures are checked against all of them, but the last one
            (the newest one) is used to sign.
        digest_size: Size of digest in bytes.
        person: Personalisation string to force the hash function to produce
            different digests for the same input. It is derived using BLAKE to
            ensure it fits the hasher limits, so it has no practical size limit.

    Raises:
        InvalidOptionError: A parameter is out of bounds.
    """
    self._hasher: typing.Type[typing.Union[hashlib.blake2b, hashlib.blake2s]]
    self._hasher = getattr(hashlib, hasher)

    super().__init__(hasher, secrets=secrets, digest_size=digest_size, person=person)

max_digest_size: typing.Optional[int] property

Get the maximum digest size, if any.

salt_size: int property

Get the salt size of the hasher.

digest(data, *, key, salt)

Get a hash digest using the hasher in keyed hashing mode.

Source code in blake2signer/hashers/blakehashers.py
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
def digest(
    self,
    data: bytes,
    *,
    key: bytes,
    salt: bytes,
) -> bytes:
    """Get a hash digest using the hasher in keyed hashing mode."""
    return self._hasher(
        data,
        digest_size=self._digest_size,
        key=key,
        salt=salt,
        person=self._person,
    ).digest()

BLAKE3Hasher(hasher, *, secrets, digest_size, person)

Bases: BLAKEHasher

Hasher interface with BLAKE3.

BLAKE hasher to interface with different BLAKE versions.

Parameters:

Name Type Description Default
hasher HasherChoice

Hash function to use.

required

Other Parameters:

Name Type Description
secrets Tuple[bytes, ...]

A tuple of secret values which are derived using BLAKE to produce the signing key, to ensure they fit the hasher limits (so they have no practical size limit), from oldest to newest. This allows secret rotation: signatures are checked against all of them, but the last one (the newest one) is used to sign.

digest_size int

Size of digest in bytes.

person bytes

Personalisation string to force the hash function to produce different digests for the same input. It is derived using BLAKE to ensure it fits the hasher limits, so it has no practical size limit.

Raises:

Type Description
InvalidOptionError

A parameter is out of bounds.

MissingDependencyError

A required dependency is not met.

Source code in blake2signer/hashers/blakehashers.py
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
def __init__(
    self,
    hasher: HasherChoice,
    *,
    secrets: typing.Tuple[bytes, ...],
    digest_size: int,
    person: bytes,
) -> None:
    """BLAKE hasher to interface with different BLAKE versions.

    Args:
        hasher: Hash function to use.

    Keyword Args:
        secrets: A tuple of secret values which are derived using BLAKE to produce
            the signing key, to ensure they fit the hasher limits (so they have
            no practical size limit), from oldest to newest. This allows secret
            rotation: signatures are checked against all of them, but the last one
            (the newest one) is used to sign.
        digest_size: Size of digest in bytes.
        person: Personalisation string to force the hash function to produce
            different digests for the same input. It is derived using BLAKE to
            ensure it fits the hasher limits, so it has no practical size limit.

    Raises:
        InvalidOptionError: A parameter is out of bounds.
        MissingDependencyError: A required dependency is not met.
    """
    # I'm purposefully omitting further validation of this hasher choice, because
    # that is handled by the signer, which is also responsible for casting a
    # BLAKE2Hasher or BLAKE3Hasher correspondingly.
    self._hasher_choice = hasher
    self._digest_size = self._validate_digest_size(digest_size)
    self._person = self._derive_person(person)
    self._keys = self._derive_keys(secrets, person=self._person)

max_digest_size: typing.Optional[int] property

Get the maximum digest size of the hasher, if any.

salt_size: int property

Get the salt size of the hasher.

digest(data, *, key, salt)

Get a hash digest using the hasher in keyed hashing mode.

Source code in blake2signer/hashers/blakehashers.py
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
def digest(
    self,
    data: bytes,
    *,
    key: bytes,
    salt: bytes,
) -> bytes:
    """Get a hash digest using the hasher in keyed hashing mode."""
    # BLAKE3 doesn't support salt nor personalisation, so there are a few
    # options to consider. Check following snippet:
    # https://gitlab.com/hackancuba/blake2signer/-/snippets/2132545
    payload = salt + self._person + data
    hasher = blake3(payload, key=key)

    return hasher.digest(length=self._digest_size)

HasherChoice

Bases: str, Enum

Hasher selection choices.

has_blake3()

Return True if the blake3 package is installed.

Source code in blake2signer/hashers/blake3_package.py
26
27
28
def has_blake3() -> bool:
    """Return True if the `blake3` package is installed."""
    return _HAS_BLAKE3

blake3

blake3(data: bytes = b'', /, *, key: bytes | None = None, derive_key_context: bytes | None = None, max_threads: int = 1, usedforsecurity: bool = True)

An incremental BLAKE3 hasher, which can accept any number of writes. The interface is similar to hashlib.blake2b or hashlib.md5 from the standard library.

Parameters:

Name Type Description Default
data bytes Input bytes to hash. Setting this to non-None is equivalent to calling update on the returned hasher. b''

Other Parameters:

Name Type Description Default
key bytes A 32-byte key. Setting this to non-None enables the BLAKE3 keyed hashing mode. None
derive_key_context bytes A hardcoded, globally unique, application-specific context string. Setting this to non-None enables the BLAKE3 key derivation mode. derive_key_context and key cannot be used at the same time. None
max_threads int The maximum number of threads that the implementation may use for hashing. The default value is 1, meaning single-threaded. max_threads may be any positive integer, or the value of the class attribute blake3.AUTO, which lets the implementation use as many threads as it likes. (Currently this means a number of threads equal to the number of logical CPU cores, but this is not guaranteed.) The actual number of threads used may be less than the maximum and may change over time. API-compatible reimplementations of this library may also ignore this parameter entirely, if they don't support multithreading. 1
usedforsecurity bool Currently ignored. See the standard hashlib docs. True