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=6, 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 |
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 |
int |
Set the desired compression level when using compression, where 1 is the fastest and least compressed and 9 the slowest and most compressed (defaults to 6). Note that the performance impact is for both compression and decompression. |
6 |
force_compression |
bool |
Force compression even if it would be
detrimental for performance or size. This parameter overrides
|
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: int = 6,
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 (defaults to 6). 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=6, 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 |
int |
Set the desired compression level when using compression, where 1 is the fastest and least compressed and 9 the slowest and most compressed (defaults to 6). Note that the performance impact is for both compression and decompression. |
6 |
force_compression |
bool |
Force compression even if it would be
detrimental for performance or size. This parameter overrides
|
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: int = 6,
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 (defaults to 6). 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=6, 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 |
int |
Set the desired compression level when using compression, where 1 is the fastest and least compressed and 9 the slowest and most compressed (defaults to 6). Note that the performance impact is for both compression and decompression. |
6 |
force_compression |
bool |
Force compression even if it would be
detrimental for performance or size. This parameter overrides
|
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: int = 6,
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 (defaults to 6). 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 |
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)