Skip to content

Signers

blake2signer.signers.Blake2Signer

BLAKE2 in keyed hashing mode for signing data.

Examples:

>>> data = b'facundo castro presente'
>>> secret_key = b'a very secret string'
>>> signer = Blake2Signer(
>>>     secret_key,
>>>     personalisation=b'the-data-signer',  # Make it unique per instance
>>> )
>>> # Sign, and i.e. store the data in a cookie
>>> signed: bytes = signer.sign(data)
>>> cookie = {'data': signed}
>>> # To verify and recover data simply use unsign: you will either get the
>>> # data, or a `SignerError` subclass exception (it is recommended to use
>>> # `SignedDataError` given it is more specific and prevents masking other
>>> # unrelated errors).
>>> try:
>>>     unsigned = signer.unsign(cookie.get('data', ''))
>>> except errors.SignedDataError:
>>>     # Can't trust given data so set a default, break current process, etc.
>>>     unsigned = b''

sign(self, data)

Sign given data and produce a stream composed of it, salt and signature.

Note that given data is not encrypted, only signed. To recover data from it, while validating the signature, use unsign.

The signature and salt are encoded using the chosen encoder. Data is left as-is.

For deterministic signatures, no salt is used. For non-deterministic ones, the salt is a cryptographically secure pseudorandom string generated for this signature only (meaning that the signature always changes even when the payload stays the same).

If given data is not bytes, a conversion will be applied assuming it's UTF-8 encoded. You should prefer to properly encode strings and passing bytes to this function.

Parameters:

Name Type Description Default
data ~AnyStr

Data to sign.

required

Returns:

Type Description
bytes

A signed stream composed of salt, signature and data.

Exceptions:

Type Description
ConversionError

Data can't be converted to bytes.

Source code in blake2signer/signers.py
def sign(self, data: typing.AnyStr) -> bytes:
    """Sign given data and produce a stream composed of it, salt and signature.

    Note that given data is _not_ encrypted, only signed. To recover data from
    it, while validating the signature, use `unsign`.

    The signature and salt are encoded using the chosen encoder.
    Data is left as-is.

    For deterministic signatures, no salt is used. For non-deterministic ones,
    the salt is a cryptographically secure pseudorandom string generated for
    this signature only (meaning that the signature always changes even when
    the payload stays the same).

    If given data is not bytes, a conversion will be applied assuming it's
    UTF-8 encoded. You should prefer to properly encode strings and passing
    bytes to this function.

    Args:
        data: Data to sign.

    Returns:
        A signed stream composed of salt, signature and data.

    Raises:
        ConversionError: Data can't be converted to bytes.
    """
    data_b = self._force_bytes(data)

    return self._compose(data_b, signature=self._sign(data_b))

sign_parts(self, data)

Sign given data and produce a container with it and salted signature.

This method is identical to sign, but it produces a container instead of a stream, in case of needing to handle data and signature separately.

Note that given data is not encrypted, only signed. To recover data from it, while validating the signature, use unsign_parts.

The signature and salt are encoded using the chosen encoder. Data is left as-is.

For deterministic signatures, no salt is used. For non-deterministic ones, the salt is a cryptographically secure pseudorandom string generated for this signature only (meaning that the signature always changes even when the payload stays the same).

If given data is not bytes, a conversion will be applied assuming it's UTF-8 encoded. You should prefer to properly encode strings and passing bytes to this function.

Parameters:

Name Type Description Default
data ~AnyStr

Data to sign.

required

Returns:

Type Description
Blake2Signature

A container with data and its salted signature.

Exceptions:

Type Description
ConversionError

Data can't be converted to bytes.

Source code in blake2signer/signers.py
def sign_parts(self, data: typing.AnyStr) -> Blake2Signature:
    """Sign given data and produce a container with it and salted signature.

    This method is identical to `sign`, but it produces a container instead
    of a stream, in case of needing to handle data and signature separately.

    Note that given data is _not_ encrypted, only signed. To recover data from
    it, while validating the signature, use `unsign_parts`.

    The signature and salt are encoded using the chosen encoder.
    Data is left as-is.

    For deterministic signatures, no salt is used. For non-deterministic ones,
    the salt is a cryptographically secure pseudorandom string generated for
    this signature only (meaning that the signature always changes even when
    the payload stays the same).

    If given data is not bytes, a conversion will be applied assuming it's
    UTF-8 encoded. You should prefer to properly encode strings and passing
    bytes to this function.

    Args:
        data: Data to sign.

    Returns:
        A container with data and its salted signature.

    Raises:
        ConversionError: Data can't be converted to bytes.
    """
    data_b = self._force_bytes(data)

    return Blake2Signature(data=data_b, signature=self._sign(data_b))

unsign(self, signed_data)

Verify a stream signed by sign and recover original data.

If given data is not bytes, a conversion will be applied assuming it's UTF-8 encoded. You should prefer to properly encode strings and passing bytes to this function.

Parameters:

Name Type Description Default
signed_data ~AnyStr

Signed data to unsign.

required

Returns:

Type Description
bytes

Original data.

Exceptions:

Type Description
ConversionError

Signed data can't be converted to bytes.

SignatureError

Signed data structure is not valid.

InvalidSignatureError

Signed data signature is invalid.

Source code in blake2signer/signers.py
def unsign(self, signed_data: typing.AnyStr) -> bytes:
    """Verify a stream signed by `sign` and recover original data.

    If given data is not bytes, a conversion will be applied assuming it's
    UTF-8 encoded. You should prefer to properly encode strings and passing
    bytes to this function.

    Args:
        signed_data: Signed data to unsign.

    Returns:
        Original data.

    Raises:
        ConversionError: Signed data can't be converted to bytes.
        SignatureError: Signed data structure is not valid.
        InvalidSignatureError: Signed data signature is invalid.
    """
    return self._unsign(self._decompose(self._force_bytes(signed_data)))

unsign_parts(self, signature)

Verify a container signed by sign_parts and recover original data.

This method is identical to unsign, but it reads a container instead of a stream.

If given container is not bytes, a conversion will be applied assuming it's UTF-8 encoded. You should prefer to properly encode strings and passing a bytes container to this function.

Parameters:

Name Type Description Default
signature Union[blake2signer.bases.Blake2Signature, blake2signer.bases.Blake2SignatureDump]

Signed data container to unsign.

required

Returns:

Type Description
bytes

Original data.

Exceptions:

Type Description
ConversionError

Signed data can't be converted to bytes.

SignatureError

Signed data structure is not valid.

InvalidSignatureError

Signed data signature is invalid.

Source code in blake2signer/signers.py
def unsign_parts(
    self,
    signature: typing.Union[Blake2Signature, Blake2SignatureDump],
) -> bytes:
    """Verify a container signed by `sign_parts` and recover original data.

    This method is identical to `unsign`, but it reads a container instead of
    a stream.

    If given container is not bytes, a conversion will be applied assuming it's
    UTF-8 encoded. You should prefer to properly encode strings and passing
    a bytes container to this function.

    Args:
        signature: Signed data container to unsign.

    Returns:
        Original data.

    Raises:
        ConversionError: Signed data can't be converted to bytes.
        SignatureError: Signed data structure is not valid.
        InvalidSignatureError: Signed data signature is invalid.
    """
    signature = self._force_bytes_parts(signature)
    # It's easier to just join the parts together and unsign the stream.
    signed_data = self._compose(signature.data, signature=signature.signature)

    return self.unsign(signed_data)

blake2signer.signers.Blake2TimestampSigner

BLAKE2 in keyed hashing mode for signing data with timestamp.

Examples:

>>> data = b'facundo castro presente'
>>> secret_key = b'a very secret string'
>>> signer = Blake2TimestampSigner(
>>>     secret_key,
>>>     personalisation=b'the-data-time-signer',  # Make it unique per instance
>>> )
>>> # Sign, and i.e. store the data in a cookie
>>> signed: bytes = signer.sign(data)
>>> cookie = {'data': signed}
>>> # To verify and recover data simply use unsign: you will either get the
>>> # data, or a `SignerError` subclass exception (it is recommended to use
>>> # `SignedDataError` given it is more specific and prevents masking other
>>> # unrelated errors). You need to specify the signature age in seconds
>>> # (or a timedelta instance). If more than said seconds since the signature
>>> # was made have passed then an `ExpiredSignatureError` is raised.
>>> try:
>>>     unsigned = signer.unsign(cookie.get('data', ''), max_age=10)
>>> except errors.SignedDataError:
>>>     # Can't trust given data so set a default, break current process, etc.
>>>     unsigned = b''

sign(self, data)

Sign given data and produce a stream of it, timestamp, salt and signature.

Note that given data is not encrypted, only signed. To recover data from it, while validating the signature and timestamp, use unsign.

The signature, salt and timestamp are encoded using chosen encoder. Data is left as-is.

For deterministic signatures, no salt is used. For non-deterministic ones, the salt is a cryptographically secure pseudorandom string generated for this signature only (meaning that the signature always changes even when the payload stays the same).

If given data is not bytes, a conversion will be applied assuming it's UTF-8 encoded. You should prefer to properly encode strings and passing bytes to this function.

Parameters:

Name Type Description Default
data ~AnyStr

Data to sign.

required

Returns:

Type Description
bytes

A signed stream composed of salt, signature, timestamp and data.

Exceptions:

Type Description
ConversionError

Data can't be converted to bytes.

Source code in blake2signer/signers.py
def sign(self, data: typing.AnyStr) -> bytes:
    """Sign given data and produce a stream of it, timestamp, salt and signature.

    Note that given data is _not_ encrypted, only signed. To recover data from
    it, while validating the signature and timestamp, use `unsign`.

    The signature, salt and timestamp are encoded using chosen encoder.
    Data is left as-is.

    For deterministic signatures, no salt is used. For non-deterministic ones,
    the salt is a cryptographically secure pseudorandom string generated for
    this signature only (meaning that the signature always changes even when
    the payload stays the same).

    If given data is not bytes, a conversion will be applied assuming it's
    UTF-8 encoded. You should prefer to properly encode strings and passing
    bytes to this function.

    Args:
        data: Data to sign.

    Returns:
        A signed stream composed of salt, signature, timestamp and data.

    Raises:
        ConversionError: Data can't be converted to bytes.
    """
    data_b = self._force_bytes(data)

    return self._compose(data_b, signature=self._sign_with_timestamp(data_b))

sign_parts(self, data)

Sign given data and produce a container of it, timestamp, salt and signature.

This method is identical to sign, but it produces a container instead of a stream, in case of needing to handle data and signature separately.

Note that given data is not encrypted, only signed. To recover data from it, while validating the signature and timestamp, use unsign_parts.

The signature, salt and timestamp are encoded using chosen encoder. Data is left as-is.

For deterministic signatures, no salt is used. For non-deterministic ones, the salt is a cryptographically secure pseudorandom string generated for this signature only (meaning that the signature always changes even when the payload stays the same).

If given data is not bytes, a conversion will be applied assuming it's UTF-8 encoded. You should prefer to properly encode strings and passing bytes to this function.

Parameters:

Name Type Description Default
data ~AnyStr

Data to sign.

required

Returns:

Type Description
Blake2Signature

A container with data and its timestamped salted signature.

Exceptions:

Type Description
ConversionError

Data can't be converted to bytes.

Source code in blake2signer/signers.py
def sign_parts(self, data: typing.AnyStr) -> Blake2Signature:
    """Sign given data and produce a container of it, timestamp, salt and signature.

    This method is identical to `sign`, but it produces a container instead
    of a stream, in case of needing to handle data and signature separately.

    Note that given data is _not_ encrypted, only signed. To recover data from
    it, while validating the signature and timestamp, use `unsign_parts`.

    The signature, salt and timestamp are encoded using chosen encoder.
    Data is left as-is.

    For deterministic signatures, no salt is used. For non-deterministic ones,
    the salt is a cryptographically secure pseudorandom string generated for
    this signature only (meaning that the signature always changes even when
    the payload stays the same).

    If given data is not bytes, a conversion will be applied assuming it's
    UTF-8 encoded. You should prefer to properly encode strings and passing
    bytes to this function.

    Args:
        data: Data to sign.

    Returns:
        A container with data and its timestamped salted signature.

    Raises:
        ConversionError: Data can't be converted to bytes.
    """
    data_b = self._force_bytes(data)

    return Blake2Signature(data=data_b, signature=self._sign_with_timestamp(data_b))

unsign(self, signed_data, *, max_age)

Verify a stream signed and timestamped by sign and recover data.

If given data is not bytes, a conversion will be applied assuming it's UTF-8 encoded. You should prefer to properly encode strings and passing bytes to this function.

Parameters:

Name Type Description Default
signed_data ~AnyStr

Signed data to unsign.

required
max_age Union[int, float, datetime.timedelta]

Ensure the signature is not older than this time in seconds.

required

Returns:

Type Description
bytes

Original data.

Exceptions:

Type Description
ConversionError

Signed data can't be converted to bytes.

SignatureError

Signed data structure is not valid.

InvalidSignatureError

Signed data signature is invalid.

ExpiredSignatureError

Signed data signature has expired.

DecodeError

Timestamp can't be decoded.

Source code in blake2signer/signers.py
def unsign(
    self,
    signed_data: typing.AnyStr,
    *,
    max_age: typing.Union[int, float, timedelta],
) -> bytes:
    """Verify a stream signed and timestamped by `sign` and recover data.

    If given data is not bytes, a conversion will be applied assuming it's
    UTF-8 encoded. You should prefer to properly encode strings and passing
    bytes to this function.

    Args:
        signed_data: Signed data to unsign.
        max_age: Ensure the signature is not older than this time in seconds.

    Returns:
        Original data.

    Raises:
        ConversionError: Signed data can't be converted to bytes.
        SignatureError: Signed data structure is not valid.
        InvalidSignatureError: Signed data signature is invalid.
        ExpiredSignatureError: Signed data signature has expired.
        DecodeError: Timestamp can't be decoded.
    """
    return self._unsign_with_timestamp(
        self._decompose(self._force_bytes(signed_data)),
        max_age=max_age,
    )

unsign_parts(self, signature, *, max_age)

Verify a container signed by sign_parts and recover original data.

This method is identical to unsign, but it reads a container instead of a stream.

If given container is not bytes, a conversion will be applied assuming it's UTF-8 encoded. You should prefer to properly encode strings and passing a bytes container to this function.

Parameters:

Name Type Description Default
signature Union[blake2signer.bases.Blake2Signature, blake2signer.bases.Blake2SignatureDump]

Signed data container to unsign.

required
max_age Union[int, float, datetime.timedelta]

Ensure the signature is not older than this time in seconds.

required

Returns:

Type Description
bytes

Original data.

Exceptions:

Type Description
ConversionError

Signed data can't be converted to bytes.

SignatureError

Signed data structure is not valid.

InvalidSignatureError

Signed data signature is invalid.

ExpiredSignatureError

Signed data signature has expired.

DecodeError

Timestamp can't be decoded.

Source code in blake2signer/signers.py
def unsign_parts(
    self,
    signature: typing.Union[Blake2Signature, Blake2SignatureDump],
    *,
    max_age: typing.Union[int, float, timedelta],
) -> bytes:
    """Verify a container signed by `sign_parts` and recover original data.

    This method is identical to `unsign`, but it reads a container instead of
    a stream.

    If given container is not bytes, a conversion will be applied assuming it's
    UTF-8 encoded. You should prefer to properly encode strings and passing
    a bytes container to this function.

    Args:
        signature: Signed data container to unsign.
        max_age: Ensure the signature is not older than this time in seconds.

    Returns:
        Original data.

    Raises:
        ConversionError: Signed data can't be converted to bytes.
        SignatureError: Signed data structure is not valid.
        InvalidSignatureError: Signed data signature is invalid.
        ExpiredSignatureError: Signed data signature has expired.
        DecodeError: Timestamp can't be decoded.
    """
    sig = self._force_bytes_parts(signature)
    # It's easier to just join the parts together and unsign the stream.
    signed_data = self._compose(sig.data, signature=sig.signature)

    return self.unsign(signed_data, max_age=max_age)

blake2signer.signers.Blake2SerializerSigner

BLAKE2 for signing and optionally timestamping serialized data.

It uses BLAKE2 in keyed hashing mode, and it can handle data serialization, compression and encoding.

Examples:

>>> data = {'message': 'attack at dawn', 'extra': [1, 2, 3, 4]}
>>> secret_key = b'a very secret string'
>>> signer = Blake2SerializerSigner(
>>>     secret_key,
>>>     max_age=timedelta(days=1),
>>>     personalisation=b'the-cookie-signer',  # Make it unique per instance
>>> )
>>> # Sign, and i.e. store the data in a cookie
>>> signed: str = signer.dumps(data)  # Compression is enabled by default
>>> cookie = {'data': signed}
>>> # To verify and recover data simply use loads: you will either get the
>>> # data, or a `SignerError` subclass exception (it is recommended to use
>>> # `SignedDataError` given it is more specific and prevents masking other
>>> # unrelated errors).
>>> try:
>>>     unsigned = signer.loads(cookie.get('data', ''))
>>> except errors.SignedDataError:
>>>     # Can't trust given data so set a default, break current process, etc.
>>>     unsigned = {'message': '', 'extra': []}

Note

If compressing data turns out to be detrimental then data won't be compressed. If you know that from beforehand and don't need compression, you can disable it: signed: str = signer.dumps(data, compress=False). Likewise, you can force compression using: signed: str = signer.dumps(data, force_compression=True).

__init__(self, secret, *, max_age=None, personalisation=b'', digest_size=None, hasher=<HasherChoice.blake2b: 'blake2b'>, deterministic=False, separator=b'.', encoder=<class 'blake2signer.encoders.B64URLEncoder'>, serializer=<class 'blake2signer.serializers.JSONSerializer'>, compressor=<class 'blake2signer.compressors.ZlibCompressor'>, compression_flag=b'.', compression_ratio=5.0) special

Serialize, sign and verify serialized signed data using BLAKE2.

It uses BLAKE2 in keyed hashing mode, and it can handle data serialization, compression and encoding.

Setting max_age will produce a timestamped signed stream.

Parameters:

Name Type Description Default
secret Union[str, bytes]

Secret value which will be derived using BLAKE2 to produce the signing key. The minimum secret size is enforced to 16 bytes and there is no maximum since the key will be derived to the maximum supported size.

required
max_age Union[NoneType, int, float, datetime.timedelta]

Use a timestamp signer instead of a regular one to ensure that the signature is not older than this time in seconds.

None
personalisation Union[str, bytes]

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

b''
digest_size Optional[int]

Size of output signature (digest) in bytes (defaults to 16 bytes). The minimum size is enforced to 16 bytes.

None
hasher Union[blake2signer.bases.HasherChoice, str]

Hash function to use: blake2b (default) or blake2s.

<HasherChoice.blake2b: 'blake2b'>
deterministic bool

Define if signatures are deterministic or non-deterministic (default). Non-deterministic sigs are preferred, and achieved through the use of a random salt. For deterministic sigs, no salt is used: this means that for the same payload, the same sig is obtained (the advantage is that the sig is shorter). Note that this assumes that the serializer and compressor are always deterministic.

False
separator Union[str, bytes]

Character to separate the signature and the payload. It must not belong to the encoder alphabet and be ASCII (defaults to ".").

b'.'
encoder Type[blake2signer.interfaces.EncoderInterface]

Encoder class to use (defaults to a Base64 URL safe encoder).

<class 'blake2signer.encoders.B64URLEncoder'>
serializer Type[blake2signer.interfaces.SerializerInterface]

Serializer class to use (defaults to a JSON serializer).

<class 'blake2signer.serializers.JSONSerializer'>
compressor Type[blake2signer.interfaces.CompressorInterface]

Compressor class to use (defaults to a Zlib compressor).

<class 'blake2signer.compressors.ZlibCompressor'>
compression_flag Union[str, bytes]

Character to mark the payload as compressed. It must not belong to the encoder alphabet and be ASCII (defaults to ".").

b'.'
compression_ratio Union[int, float]

Desired minimal compression ratio, between 0 and below 100 (defaults to 5). It is used to calculate when to consider a payload sufficiently compressed to detect detrimental compression. By default, if compression achieves less than 5% of size reduction, it is considered detrimental.

5.0

Exceptions:

Type Description
ConversionError

A bytes parameter is not bytes and can't be converted to bytes.

InvalidOptionError

A parameter is out of bounds.

Source code in blake2signer/signers.py
def __init__(
    self,
    secret: typing.Union[str, bytes],
    *,
    max_age: typing.Union[None, int, float, timedelta] = None,
    personalisation: typing.Union[str, bytes] = b'',
    digest_size: typing.Optional[int] = None,
    hasher: typing.Union[HasherChoice, str] = HasherChoice.blake2b,
    deterministic: bool = False,
    separator: typing.Union[str, bytes] = b'.',
    encoder: typing.Type[EncoderInterface] = B64URLEncoder,
    serializer: typing.Type[SerializerInterface] = JSONSerializer,
    compressor: typing.Type[CompressorInterface] = ZlibCompressor,
    compression_flag: typing.Union[str, bytes] = b'.',
    compression_ratio: typing.Union[int, float] = 5.0,
) -> None:
    """Serialize, sign and verify serialized signed data using BLAKE2.

    It uses BLAKE2 in keyed hashing mode, and it can handle data serialization,
    compression and encoding.

    Setting `max_age` will produce a timestamped signed stream.

    Args:
        secret: Secret value which will be derived using BLAKE2 to
            produce the signing key. The minimum secret size is enforced to
            16 bytes and there is no maximum since the key will be derived to
            the maximum supported size.
        max_age (optional): Use a timestamp signer instead of a regular one
            to ensure that the signature is not older than this time in seconds.
        personalisation (optional): Personalisation string to force the hash
            function to produce different digests for the same input. It is
            derived using BLAKE2 to ensure it fits the hasher limits, so it
            has no practical size limit. It defaults to the class name.
        digest_size (optional): Size of output signature (digest) in bytes
            (defaults to 16 bytes). The minimum size is enforced to 16 bytes.
        hasher (optional): Hash function to use: blake2b (default) or blake2s.
        deterministic (optional): Define if signatures are deterministic or
            non-deterministic (default). Non-deterministic sigs are preferred,
            and achieved through the use of a random salt. For deterministic
            sigs, no salt is used: this means that for the same payload, the
            same sig is obtained (the advantage is that the sig is shorter).
            Note that this assumes that the serializer and compressor are
            always deterministic.
        separator (optional): Character to separate the signature and the
            payload. It must not belong to the encoder alphabet and be ASCII
            (defaults to ".").
        encoder (optional): Encoder class to use (defaults to a Base64 URL
            safe encoder).
        serializer (optional): Serializer class to use (defaults to a JSON
            serializer).
        compressor (optional): Compressor class to use (defaults to a Zlib
            compressor).
        compression_flag (optional): Character to mark the payload as compressed.
            It must not belong to the encoder alphabet and be ASCII (defaults
            to ".").
        compression_ratio (optional): Desired minimal compression ratio, between
            0 and below 100 (defaults to 5). It is used to calculate when
            to consider a payload sufficiently compressed to detect detrimental
            compression. By default, if compression achieves less than 5% of
            size reduction, it is considered detrimental.

    Raises:
        ConversionError: A bytes parameter is not bytes and can't be converted
            to bytes.
        InvalidOptionError: A parameter is out of bounds.
    """
    super().__init__(
        secret,
        max_age=max_age,
        personalisation=personalisation,
        digest_size=digest_size,
        hasher=hasher,
        deterministic=deterministic,
        separator=separator,
        serializer=serializer,
        compressor=compressor,
        encoder=encoder,
        compression_flag=compression_flag,
        compression_ratio=compression_ratio,
    )

    if self._compression_flag in self._encoder.alphabet:
        raise errors.InvalidOptionError(
            'the compression flag character must not belong to the encoder alphabet',
        )

dump(self, data, file, *, compress=True, compression_level=None, force_compression=False, serializer_kwargs=None)

Serialize and sign data to file optionally compressing and/or timestamping it.

This method is identical to :meth:dumps, but it dumps into a file, which must be a .write()-supporting file-like object, and returns the written value for convenience.

Note that given data is not encrypted, only signed. To recover data from the produced string, while validating the signature (and timestamp if any), use loads.

Data will be serialized, optionally compressed, and encoded before being signed. This means that it must be of any type serializable by the chosen serializer, i.e. for a JSON serializer: str, int, float, list, tuple, bool, None or dict, or a composition of those (tuples are unserialized as lists).

If max_age was specified then the stream will be timestamped.

For deterministic signatures, no salt is used. For non-deterministic ones, the salt is a cryptographically secure pseudorandom string generated for this signature only (meaning that the signature always changes even when the payload stays the same).

The full flow is as follows, where optional actions are marked between brackets: data -> serialize -> [compress] -> [timestamp] -> encode -> sign

Parameters:

Name Type Description Default
data Any

Any serializable object.

required
file IO

A .write()-supporting file-like object.

required
compress bool

Compress data (default) after serializing it and decompress it before unserializing. For low entropy payloads such as human-readable text, it's beneficial from around ~30bytes, and detrimental if smaller. For high entropy payloads like pseudorandom text, it's beneficial from around ~300bytes and detrimental if lower than ~100bytes. You can safely enable it since a size check is done so if compression turns detrimental then it won't be used. If you know from beforehand that data can't be compressed and don't want to waste resources trying, set it to False.

True
compression_level Optional[int]

Set the desired compression level when using compression, where 1 is the fastest and least compressed and 9 the slowest and most compressed. The default value depends on the compressor being used. Note that the performance impact is for both compression and decompression.

None
force_compression bool

Force compression even if it would be detrimental for performance or size. This parameter overrides compress.

False
serializer_kwargs Optional[Dict[str, Any]]

Provide keyword arguments for the serializer.

None

Exceptions:

Type Description
SerializationError

Data can't be serialized.

CompressionError

Data can't be compressed or compression level is invalid.

EncodeError

Data can't be encoded.

FileError

File can't be written.

Source code in blake2signer/signers.py
def dump(
    self,
    data: typing.Any,
    file: typing.IO,
    *,
    compress: bool = True,
    compression_level: typing.Optional[int] = None,
    force_compression: bool = False,
    serializer_kwargs: typing.Optional[typing.Dict[str, typing.Any]] = None,
) -> str:
    """Serialize and sign data to file optionally compressing and/or timestamping it.

    This method is identical to :meth:`dumps`, but it dumps into a file, which
    must be a `.write()`-supporting file-like object, and returns the written
    value for convenience.

    Note that given data is _not_ encrypted, only signed. To recover data from
    the produced string, while validating the signature (and timestamp if any),
    use `loads`.

    Data will be serialized, optionally compressed, and encoded before being
    signed. This means that it must be of any type serializable by the chosen
    serializer, i.e. for a JSON serializer: str, int, float, list, tuple, bool,
    None or dict, or a composition of those (tuples are unserialized as lists).

    If `max_age` was specified then the stream will be timestamped.

    For deterministic signatures, no salt is used. For non-deterministic ones,
    the salt is a cryptographically secure pseudorandom string generated for
    this signature only (meaning that the signature always changes even when
    the payload stays the same).

    The full flow is as follows, where optional actions are marked between brackets:
    data -> serialize -> [compress] -> [timestamp] -> encode -> sign

    Args:
        data: Any serializable object.
        file: A `.write()`-supporting file-like object.
        compress (optional): Compress data (default) after serializing it and
            decompress it before unserializing. For low entropy payloads such
            as human-readable text, it's beneficial from around ~30bytes, and
            detrimental if smaller. For high entropy payloads like pseudorandom
            text, it's beneficial from around ~300bytes and detrimental if lower
            than ~100bytes. You can safely enable it since a size check is done
            so if compression turns detrimental then it won't be used. If you
            know from beforehand that data can't be compressed and don't want
            to waste resources trying, set it to False.
        compression_level (optional): Set the desired compression level when
            using compression, where 1 is the fastest and least compressed
            and 9 the slowest and most compressed. The default value depends
            on the compressor being used. Note that the performance impact is
            for both compression and decompression.
        force_compression (optional): Force compression even if it would be
            detrimental for performance or size. This parameter overrides
            `compress`.
        serializer_kwargs (optional): Provide keyword arguments for the serializer.

    Raises:
        SerializationError: Data can't be serialized.
        CompressionError: Data can't be compressed or compression level is invalid.
        EncodeError: Data can't be encoded.
        FileError: File can't be written.
    """
    signed = self.dumps(
        data,
        compress=compress,
        compression_level=compression_level,
        force_compression=force_compression,
        serializer_kwargs=serializer_kwargs,
    )

    # Signed value is ASCII so ConversionError can't happen.
    self._write(file, signed)

    return signed

dumps(self, data, *, compress=True, compression_level=None, force_compression=False, serializer_kwargs=None)

Serialize and sign data, optionally compressing and/or timestamping it.

Note that given data is not encrypted, only signed. To recover data from the produced string, while validating the signature (and timestamp if any), use loads.

Data will be serialized, optionally compressed, and encoded before being signed. This means that it must be of any type serializable by the chosen serializer, i.e. for a JSON serializer: str, int, float, list, tuple, bool, None or dict, or a composition of those (tuples are unserialized as lists).

If max_age was specified then the stream will be timestamped.

For deterministic signatures, no salt is used. For non-deterministic ones, the salt is a cryptographically secure pseudorandom string generated for this signature only (meaning that the signature always changes even when the payload stays the same).

The full flow is as follows, where optional actions are marked between brackets: data -> serialize -> [compress] -> [timestamp] -> encode -> sign

Parameters:

Name Type Description Default
data Any

Any serializable object.

required
compress bool

Compress data (default) after serializing it and decompress it before unserializing. For low entropy payloads such as human-readable text, it's beneficial from around ~30bytes, and detrimental if smaller. For high entropy payloads like pseudorandom text, it's beneficial from around ~300bytes and detrimental if lower than ~100bytes. You can safely enable it since a size check is done so if compression turns detrimental then it won't be used. If you know from beforehand that data can't be compressed and don't want to waste resources trying, set it to False.

True
compression_level Optional[int]

Set the desired compression level when using compression, where 1 is the fastest and least compressed and 9 the slowest and most compressed. The default value depends on the compressor being used. Note that the performance impact is for both compression and decompression.

None
force_compression bool

Force compression even if it would be detrimental for performance or size. This parameter overrides compress.

False
serializer_kwargs Optional[Dict[str, Any]]

Provide keyword arguments for the serializer.

None

Returns:

Type Description
str

An encoded, signed and optionally timestamped string of serialized and optionally compressed data. This value is safe for printing or transmitting as it only contains the characters supported by the encoder and the separator, which are ASCII.

Exceptions:

Type Description
SerializationError

Data can't be serialized.

CompressionError

Data can't be compressed or compression level is invalid.

EncodeError

Data can't be encoded.

Source code in blake2signer/signers.py
def dumps(
    self,
    data: typing.Any,
    *,
    compress: bool = True,
    compression_level: typing.Optional[int] = None,
    force_compression: bool = False,
    serializer_kwargs: typing.Optional[typing.Dict[str, typing.Any]] = None,
) -> str:
    """Serialize and sign data, optionally compressing and/or timestamping it.

    Note that given data is _not_ encrypted, only signed. To recover data from
    the produced string, while validating the signature (and timestamp if any),
    use `loads`.

    Data will be serialized, optionally compressed, and encoded before being
    signed. This means that it must be of any type serializable by the chosen
    serializer, i.e. for a JSON serializer: str, int, float, list, tuple, bool,
    None or dict, or a composition of those (tuples are unserialized as lists).

    If `max_age` was specified then the stream will be timestamped.

    For deterministic signatures, no salt is used. For non-deterministic ones,
    the salt is a cryptographically secure pseudorandom string generated for
    this signature only (meaning that the signature always changes even when
    the payload stays the same).

    The full flow is as follows, where optional actions are marked between brackets:
    data -> serialize -> [compress] -> [timestamp] -> encode -> sign

    Args:
        data: Any serializable object.
        compress (optional): Compress data (default) after serializing it and
            decompress it before unserializing. For low entropy payloads such
            as human-readable text, it's beneficial from around ~30bytes, and
            detrimental if smaller. For high entropy payloads like pseudorandom
            text, it's beneficial from around ~300bytes and detrimental if lower
            than ~100bytes. You can safely enable it since a size check is done
            so if compression turns detrimental then it won't be used. If you
            know from beforehand that data can't be compressed and don't want
            to waste resources trying, set it to False.
        compression_level (optional): Set the desired compression level when
            using compression, where 1 is the fastest and least compressed
            and 9 the slowest and most compressed. The default value depends
            on the compressor being used. Note that the performance impact is
            for both compression and decompression.
        force_compression (optional): Force compression even if it would be
            detrimental for performance or size. This parameter overrides
            `compress`.
        serializer_kwargs (optional): Provide keyword arguments for the serializer.

    Returns:
        An encoded, signed and optionally timestamped string of serialized
        and optionally compressed data. This value is safe for printing or
        transmitting as it only contains the characters supported by the
        encoder and the separator, which are ASCII.

    Raises:
        SerializationError: Data can't be serialized.
        CompressionError: Data can't be compressed or compression level is invalid.
        EncodeError: Data can't be encoded.
    """
    dump = self._dumps(
        data,
        compress=compress,
        compression_level=compression_level,
        force_compression=force_compression,
        serializer_kwargs=serializer_kwargs,
    )

    # since everything is ASCII, decoding is safe
    return self._compose(dump, signature=self._proper_sign(dump)).decode()

dumps_parts(self, data, *, compress=True, compression_level=None, force_compression=False, serializer_kwargs=None)

Serialize and sign data, optionally compressing and/or timestamping it.

This method is identical to dumps, but it dumps into a container instead of a stream, in case of needing to handle data and signature separately.

Note that given data is not encrypted, only signed. To recover data from the produced string, while validating the signature (and timestamp if any), use loads_parts.

Data will be serialized, optionally compressed, and encoded before being signed. This means that it must be of any type serializable by the chosen serializer, i.e. for a JSON serializer: str, int, float, list, tuple, bool, None or dict, or a composition of those (tuples are unserialized as lists).

If max_age was specified then the stream will be timestamped.

For deterministic signatures, no salt is used. For non-deterministic ones, the salt is a cryptographically secure pseudorandom string generated for this signature only (meaning that the signature always changes even when the payload stays the same).

The full flow is as follows, where optional actions are marked between brackets: data -> serialize -> [compress] -> [timestamp] -> encode -> sign

Parameters:

Name Type Description Default
data Any

Any serializable object.

required
compress bool

Compress data (default) after serializing it and decompress it before unserializing. For low entropy payloads such as human-readable text, it's beneficial from around ~30bytes, and detrimental if smaller. For high entropy payloads like pseudorandom text, it's beneficial from around ~300bytes and detrimental if lower than ~100bytes. You can safely enable it since a size check is done so if compression turns detrimental then it won't be used. If you know from beforehand that data can't be compressed and don't want to waste resources trying, set it to False.

True
compression_level Optional[int]

Set the desired compression level when using compression, where 1 is the fastest and least compressed and 9 the slowest and most compressed. The default value depends on the compressor being used. Note that the performance impact is for both compression and decompression.

None
force_compression bool

Force compression even if it would be detrimental for performance or size. This parameter overrides compress.

False
serializer_kwargs Optional[Dict[str, Any]]

Provide keyword arguments for the serializer.

None

Returns:

Type Description
Blake2SignatureDump

A container with an encoded, signed and optionally timestamped string of serialized and optionally compressed data. This value is safe for printing or transmitting as it only contains the characters supported by the encoder and the separator, which are ASCII.

Exceptions:

Type Description
SerializationError

Data can't be serialized.

CompressionError

Data can't be compressed or compression level is invalid.

EncodeError

Data can't be encoded.

Source code in blake2signer/signers.py
def dumps_parts(
    self,
    data: typing.Any,
    *,
    compress: bool = True,
    compression_level: typing.Optional[int] = None,
    force_compression: bool = False,
    serializer_kwargs: typing.Optional[typing.Dict[str, typing.Any]] = None,
) -> Blake2SignatureDump:
    """Serialize and sign data, optionally compressing and/or timestamping it.

    This method is identical to `dumps`, but it dumps into a container instead
    of a stream, in case of needing to handle data and signature separately.

    Note that given data is _not_ encrypted, only signed. To recover data from
    the produced string, while validating the signature (and timestamp if any),
    use `loads_parts`.

    Data will be serialized, optionally compressed, and encoded before being
    signed. This means that it must be of any type serializable by the chosen
    serializer, i.e. for a JSON serializer: str, int, float, list, tuple, bool,
    None or dict, or a composition of those (tuples are unserialized as lists).

    If `max_age` was specified then the stream will be timestamped.

    For deterministic signatures, no salt is used. For non-deterministic ones,
    the salt is a cryptographically secure pseudorandom string generated for
    this signature only (meaning that the signature always changes even when
    the payload stays the same).

    The full flow is as follows, where optional actions are marked between brackets:
    data -> serialize -> [compress] -> [timestamp] -> encode -> sign

    Args:
        data: Any serializable object.
        compress (optional): Compress data (default) after serializing it and
            decompress it before unserializing. For low entropy payloads such
            as human-readable text, it's beneficial from around ~30bytes, and
            detrimental if smaller. For high entropy payloads like pseudorandom
            text, it's beneficial from around ~300bytes and detrimental if lower
            than ~100bytes. You can safely enable it since a size check is done
            so if compression turns detrimental then it won't be used. If you
            know from beforehand that data can't be compressed and don't want
            to waste resources trying, set it to False.
        compression_level (optional): Set the desired compression level when
            using compression, where 1 is the fastest and least compressed
            and 9 the slowest and most compressed. The default value depends
            on the compressor being used. Note that the performance impact is
            for both compression and decompression.
        force_compression (optional): Force compression even if it would be
            detrimental for performance or size. This parameter overrides
            `compress`.
        serializer_kwargs (optional): Provide keyword arguments for the serializer.

    Returns:
        A container with an encoded, signed and optionally timestamped string
        of serialized and optionally compressed data. This value is safe for
        printing or transmitting as it only contains the characters supported
        by the encoder and the separator, which are ASCII.

    Raises:
        SerializationError: Data can't be serialized.
        CompressionError: Data can't be compressed or compression level is invalid.
        EncodeError: Data can't be encoded.
    """
    dump = self._dumps(
        data,
        compress=compress,
        compression_level=compression_level,
        force_compression=force_compression,
        serializer_kwargs=serializer_kwargs,
    )

    # since everything is ASCII, decoding is safe
    return Blake2SignatureDump(
        data=dump.decode(),
        signature=self._proper_sign(dump).decode(),
    )

load(self, file)

Recover original data from a signed serialized file from dump.

This method is identical to loads, but it reads a file, which must be a .read()-supporting file-like object.

If max_age was specified then it will be ensured that the signature is not older than that time in seconds.

If the data was compressed, it will be decompressed before unserializing it.

The full flow is as follows, where optional actions are marked between brackets: data -> check sig -> [check timestamp] -> decode -> [decompress] -> unserialize

Parameters:

Name Type Description Default
file IO

A .read()-supporting file-like object containing data to unsign.

required

Returns:

Type Description
Any

Original data.

Exceptions:

Type Description
ConversionError

Signed data can't be converted to bytes.

SignatureError

Signed data structure is not valid.

InvalidSignatureError

Signed data signature is invalid.

ExpiredSignatureError

Signed data signature has expired.

DecodeError

Signed data can't be decoded.

DecompressionError

Signed data can't be decompressed.

UnserializationError

Signed data can't be unserialized.

FileError

File can't be read.

Source code in blake2signer/signers.py
def load(self, file: typing.IO) -> typing.Any:
    """Recover original data from a signed serialized file from `dump`.

    This method is identical to `loads`, but it reads a file, which
    must be a `.read()`-supporting file-like object.

    If `max_age` was specified then it will be ensured that the signature is
    not older than that time in seconds.

    If the data was compressed, it will be decompressed before unserializing it.

    The full flow is as follows, where optional actions are marked between brackets:
    data -> check sig -> [check timestamp] -> decode -> [decompress] -> unserialize

    Args:
        file: A `.read()`-supporting file-like object containing data to unsign.

    Returns:
        Original data.

    Raises:
        ConversionError: Signed data can't be converted to bytes.
        SignatureError: Signed data structure is not valid.
        InvalidSignatureError: Signed data signature is invalid.
        ExpiredSignatureError: Signed data signature has expired.
        DecodeError: Signed data can't be decoded.
        DecompressionError: Signed data can't be decompressed.
        UnserializationError: Signed data can't be unserialized.
        FileError: File can't be read.
    """
    return self.loads(self._read(file))

loads(self, signed_data)

Recover original data from a signed serialized string from dumps.

If max_age was specified then it will be ensured that the signature is not older than that time in seconds.

If the data was compressed, it will be decompressed before unserializing it.

The full flow is as follows, where optional actions are marked between brackets: data -> check sig -> [check timestamp] -> decode -> [decompress] -> unserialize

Parameters:

Name Type Description Default
signed_data ~AnyStr

Signed data to unsign.

required

Returns:

Type Description
Any

Original data.

Exceptions:

Type Description
ConversionError

Signed data can't be converted to bytes.

SignatureError

Signed data structure is not valid.

InvalidSignatureError

Signed data signature is invalid.

ExpiredSignatureError

Signed data signature has expired.

DecodeError

Signed data can't be decoded.

DecompressionError

Signed data can't be decompressed.

UnserializationError

Signed data can't be unserialized.

Source code in blake2signer/signers.py
def loads(self, signed_data: typing.AnyStr) -> typing.Any:
    """Recover original data from a signed serialized string from `dumps`.

    If `max_age` was specified then it will be ensured that the signature is
    not older than that time in seconds.

    If the data was compressed, it will be decompressed before unserializing it.

    The full flow is as follows, where optional actions are marked between brackets:
    data -> check sig -> [check timestamp] -> decode -> [decompress] -> unserialize

    Args:
        signed_data: Signed data to unsign.

    Returns:
        Original data.

    Raises:
        ConversionError: Signed data can't be converted to bytes.
        SignatureError: Signed data structure is not valid.
        InvalidSignatureError: Signed data signature is invalid.
        ExpiredSignatureError: Signed data signature has expired.
        DecodeError: Signed data can't be decoded.
        DecompressionError: Signed data can't be decompressed.
        UnserializationError: Signed data can't be unserialized.
    """
    parts = self._decompose(self._force_bytes(signed_data))

    return self._loads(self._proper_unsign(parts))

loads_parts(self, signature)

Recover original data from a signed serialized container from dumps_parts.

This method is identical to loads, but it reads a container instead of a stream.

If max_age was specified then it will be ensured that the signature is not older than that time in seconds.

If the data was compressed, it will be decompressed before unserializing it.

The full flow is as follows, where optional actions are marked between brackets: data -> check sig -> [check timestamp] -> decode -> [decompress] -> unserialize

Parameters:

Name Type Description Default
signature Union[blake2signer.bases.Blake2Signature, blake2signer.bases.Blake2SignatureDump]

Signed data container to unsign.

required

Returns:

Type Description
Any

Original data.

Exceptions:

Type Description
ConversionError

Signed data can't be converted to bytes.

SignatureError

Signed data structure is not valid.

InvalidSignatureError

Signed data signature is invalid.

ExpiredSignatureError

Signed data signature has expired.

DecodeError

Signed data can't be decoded.

DecompressionError

Signed data can't be decompressed.

UnserializationError

Signed data can't be unserialized.

Source code in blake2signer/signers.py
def loads_parts(
    self,
    signature: typing.Union[Blake2Signature, Blake2SignatureDump],
) -> typing.Any:
    """Recover original data from a signed serialized container from `dumps_parts`.

    This method is identical to `loads`, but it reads a container instead of
    a stream.

    If `max_age` was specified then it will be ensured that the signature is
    not older than that time in seconds.

    If the data was compressed, it will be decompressed before unserializing it.

    The full flow is as follows, where optional actions are marked between brackets:
    data -> check sig -> [check timestamp] -> decode -> [decompress] -> unserialize

    Args:
        signature: Signed data container to unsign.

    Returns:
        Original data.

    Raises:
        ConversionError: Signed data can't be converted to bytes.
        SignatureError: Signed data structure is not valid.
        InvalidSignatureError: Signed data signature is invalid.
        ExpiredSignatureError: Signed data signature has expired.
        DecodeError: Signed data can't be decoded.
        DecompressionError: Signed data can't be decompressed.
        UnserializationError: Signed data can't be unserialized.
    """
    sig = self._force_bytes_parts(signature)
    # It's easier to just join the parts together and unsign the stream.
    signed_data = self._compose(sig.data, signature=sig.signature)

    return self.loads(signed_data)