Skip to content

Comparison

Comparison against other similar libraries.

It's Dangerous

It's Dangerous Logo

Signing interface

Both itsdangerous.Signer and itsdangerous.TimestampSigner appends the signature to the given string, whereas blake2signer.Blake2Signer and blake2signer.Blake2TimestampSigner prepends it (with salt). Other than that, this package can be a drop-in replacement and vice versa.

from itsdangerous import SignatureExpired
from itsdangerous import Signer
from itsdangerous import TimestampSigner

# Signer
signer = Signer('secret-key')
print(signer.sign('my string'))
print(signer.unsign(b'my string.wh6tMHxLgJqB6oY1uT73iMlyrOA'))  # b'my string'

# Timestamp signer
signer = TimestampSigner('secret-key')
print(signer.sign('foo'))
try:
    print(signer.unsign(b'foo.YIZMkg.FQdIC8gFmkwy4w8KC05IQfzU-Gc', max_age=3600))  # b'foo'
except SignatureExpired as exc:
    print(repr(exc))  # SignatureExpired: Signature age ... > 3600 seconds
from blake2signer import Blake2Signer
from blake2signer import Blake2TimestampSigner
from blake2signer.errors import ExpiredSignatureError

# Signer
signer = Blake2Signer('super-secret-key')  # 16 bytes min size enforced
print(signer.sign('my string'))
print(signer.unsign(b'tUt_Nu7h86uvsUyQDRIm6d3T-cKlSUlt--JR_w.my string'))  # b'my string'

# Timestamp signer
signer = Blake2TimestampSigner('super-secret-key')
print(signer.sign('foo'))
try:
    print(signer.unsign(b'tUY3jX-uu4Luqaya0Yr0WgvHIaSboPiP-YwBAw.YIbw6w.foo', max_age=3600))  # b'foo'
except ExpiredSignatureError as exc:
    print(repr(exc))  # ExpiredSignatureError('signature has expired, age ... > 3600.0 seconds')

Main differences

  • itsdangerous uses sha-1 by default as hashing backend, this package uses blake2b.
  • itsdangerous creates deterministic signatures by default, this package doesn't (see the example on generating deterministic signatures).
  • itsdangerous appends signature (and timestamp) to data, this package prepends it.

Serializing interface

For serializing and signing objects, itsdangerous provides four classes: Serializer, URLSafeSerializer, TimedSerializer and URLSafeTimedSerializer. This package provides similar capabilities in a single class: Blake2SerializerSigner.
The interfaces are similar and can be used as drop-in replacements.

from itsdangerous import SignatureExpired
from itsdangerous.serializer import Serializer
from itsdangerous.timed import TimedSerializer
from itsdangerous.url_safe import URLSafeSerializer
from itsdangerous.url_safe import URLSafeTimedSerializer

# Serializer signer
signer = Serializer('secret-key')
print(signer.dumps([1, 2, 3, 4]))
print(signer.loads('[1, 2, 3, 4].r7R9RhGgDPvvWl3iNzLuIIfELmo'))  # [1, 2, 3, 4]

# Timestamp serializer signer
signer = TimedSerializer('secret-key')
print(signer.dumps([1, 2, 3, 4]))
try:
    print(signer.loads('[1, 2, 3, 4].YIZQ-w.0wubnZ3HhtaKvWuo-Kpks7F9Pfs', max_age=3600))  # [1, 2, 3, 4]
except SignatureExpired as exc:
    print(repr(exc))  # SignatureExpired: Signature age ... > 3600 seconds

# Encoder serializer signer
signer = URLSafeSerializer('secret-key')
print(signer.dumps([1, 2, 3, 4]))
print(signer.loads('WzEsMiwzLDRd.wSPHqC0gR7VUqivlSukJ0IeTDgo'))  # [1, 2, 3, 4]

# Timestamp encoder serializer signer
signer = URLSafeTimedSerializer('secret-key')
print(signer.dumps([1, 2, 3, 4]))
try:
    print(signer.loads('WzEsMiwzLDRd.YIZRkQ.1Q_nKsgoxD_JtddAyWxBBnmR87M', max_age=3600))  # [1, 2, 3, 4]
except SignatureExpired as exc:
    print(repr(exc))  # SignatureExpired: Signature age ... > 3600 seconds
from blake2signer import Blake2SerializerSigner
from blake2signer.errors import ExpiredSignatureError

# Encoder compressor serializer signer
signer = Blake2SerializerSigner('super-secret-key')  # 16 bytes min size enforced
print(signer.dumps([1, 2, 3, 4]))
print(signer.loads('0i5Gvawg0724DBwXAG8rsUegCgCL-VLhjfOQ2g.WzEsMiwzLDRd'))  # [1, 2, 3, 4]

# Timestamp encoder compressor serializer signer
signer = Blake2SerializerSigner('super-secret-key', max_age=3600)  # With timestamp
print(signer.dumps([1, 2, 3, 4]))
try:
    print(signer.loads('_zhFEz1fpIaTiUd6lk8M1u_5Q0ChEx671Mux1Q.YIcL8w.WzEsMiwzLDRd'))  # [1, 2, 3, 4]
except ExpiredSignatureError as exc:
    print(repr(exc))  # ExpiredSignatureError('signature has expired, age ... > 3600.0 seconds')

Main differences

  • itsdangerous provides four different serializers to handle different cases, this package provides just one.
  • itsdangerous can serialize without encoding data, this package can't (not directly, see the example on how to serialize without encoding).
  • itsdangerous can't easily change the encoder, compressor and/or serializer, this package can.
  • itsdangerous provides an interface to load data unsafely, this package doesn't (and probably never will).

Django's signer

Django's Logo

Signing interface

The django.core.signing.Signer appends the signature to the given string, whereas blake2signer.Blake2Signer prepends it (with salt). Other than that, this package can be a drop-in replacement and vice versa.

from django.conf import settings
from django.core.signing import SignatureExpired
from django.core.signing import Signer
from django.core.signing import TimestampSigner

settings.configure()  # Initialize Django

# Signer
signer = Signer('secret-key')
print(signer.sign('My string'))
print(signer.unsign('My string:ZMytWkz1GTS_Nk71RrVV19aB0pjYncBU3hgXOh78xk8'))  # My string

# Timestamp signer
signer = TimestampSigner('secret-key')
print(signer.sign('My string'))
try:
    print(signer.unsign('My string:1lb46Q:WXYzPtY3ICSPVSU4qqGXfJ2_UiuiOfQV4S47-q6eT70', max_age=3600))  # My string
except SignatureExpired as exc:
    print(repr(exc))  # SignatureExpired: Signature age ... > 3600 seconds
from blake2signer import Blake2Signer
from blake2signer import Blake2TimestampSigner
from blake2signer.errors import ExpiredSignatureError

# Signer
signer = Blake2Signer('super-secret-key')  # 16 bytes min size enforced
print(signer.sign('My string'))
print(signer.unsign(b'RjlBYraVdIvRuH8uYpVO3kBp4qfkt93r2EaqMQ.My string'))  # b'my string'

# Timestamp signer
signer = Blake2TimestampSigner('super-secret-key')
print(signer.sign('My string'))
try:
    print(signer.unsign(b'O8W1aRlq6_RqkDsB3FYKNXu0Tzu9ziNKWr3xDA.YI8YXQ.My string', max_age=3600))  # b'foo'
except ExpiredSignatureError as exc:
    print(repr(exc))  # ExpiredSignatureError('signature has expired, age ... > 3600.0 seconds')

Main differences

  • django uses sha-256 by default as hashing backend, this package uses blake2b.
  • django creates deterministic signatures by default, this package doesn't.
  • django appends signature (and timestamp) to data, this package prepends it.
  • django uses the character : as separator by default, this package uses ..

Serializing interface

For serializing and signing objects, Django provides two functions: dumps and loads. This package provides similar capabilities in a single class: Blake2SerializerSigner.
The interfaces are similar and can be used as drop-in replacements.

from django.conf import settings
from django.core import signing
from django.core.signing import SignatureExpired

settings.configure()  # Initialize Django

# Encoder compressor serializer signer
print(signing.dumps({'foo': 'bar'}, key='secret-key'))
print(signing.loads('eyJmb28iOiJiYXIifQ:1lb4Iy:GvulJZFUKKn60lWG8WoAYfs4SY-Ctdm-PVkApi44nlE', key='secret-key'))  # {'foo': 'bar'}

# Timestamp encoder compressor serializer signer
try:
    print(signing.loads('eyJmb28iOiJiYXIifQ:1lb4Iy:GvulJZFUKKn60lWG8WoAYfs4SY-Ctdm-PVkApi44nlE', key='secret-key', max_age=3600))  # {'foo': 'bar'}
except SignatureExpired as exc:
    print(repr(exc))  # SignatureExpired: Signature age ... > 3600 seconds
from blake2signer import Blake2SerializerSigner
from blake2signer.errors import ExpiredSignatureError

# Encoder compressor serializer signer
signer = Blake2SerializerSigner('super-secret-key')  # 16 bytes min size enforced
print(signer.dumps({'foo': 'bar'}))
print(signer.loads('Is7yyhMWydBGzqvIpynb_sEqudc6AcAYnItCow.eyJmb28iOiJiYXIifQ'))  # {'foo': 'bar'}

# Timestamp encoder compressor serializer signer
signer = Blake2SerializerSigner('super-secret-key', max_age=3600)  # With timestamp
print(signer.dumps({'foo': 'bar'}))
try:
    print(signer.loads('7nKxO-QcE60ciWiwu5OHrQz3ftKgIhh92B3pgQ.YJYbrA.eyJmb28iOiJiYXIifQ'))  # {'foo': 'bar'}
except ExpiredSignatureError as exc:
    print(repr(exc))  # ExpiredSignatureError('signature has expired, age ... > 3600.0 seconds')

Main differences

  • Django provides two functions to handle different cases, this package provides just one class.
  • Django can't easily change the encoder, compressor and/or serializer, this package can.
  • Django doesn't compress by default, this package does (and smartly: it won't compress if it turns out detrimental).

PyJWT

JWT Logo

Serializing interface

PyJWT implements RFC 7519 for JSON Web Token which is quite complex, not needed in most cases and can easily turn into a footgun; this package is uncomplicated and can be used instead on most situations. On the other hand, for a similar utility but without the many design deficits that plague JWT, see PASETO.

import jwt

print(jwt.encode({'some': 'payload'}, 'secret', algorithm='HS256'))
print(jwt.decode(
    'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzb21lIjoicGF5bG9hZCJ9.Joh1R2dYzkRvDkqv3sygm5YyK8Gi4ShZqbhK2gxcs2U',
    'secret',
    algorithms=['HS256'],
))  # {'some': 'payload'}
from blake2signer import Blake2SerializerSigner

signer = Blake2SerializerSigner('super-secret-key')  # 16 bytes min size enforced
print(signer.dumps({'some': 'payload'})
print(signer.loads('xJigCzDl2Naq3pt8dHNEZDY7ZIYLZ24U-No83g.eyJzb21lIjoicGF5bG9hZCJ9'))  # {'some': 'payload'}

Main differences

  • PyJWT can handle different algorithms dynamically - using a data header -, this package can't and never will.
  • PyJWT can't change the encoder or serializer, this package can.
  • PyJWT can't compress data, this package does (and smartly: it won't compress if it turns out detrimental).

Performance comparison

Following is the performance comparison of this lib against It's Dangerous, Django and PyJWT. Generally speaking, it is as fast or a bit faster than the other libs, so you should choose one or the other based on usability and fitting-your-needs rather than performance.

Info

Take into account that the only significant performance comparison exists when blake2b or blake2s is used as hashing algorithm, otherwise the algorithm performance may outweigh the implementation. Other algorithms are noted here to be taken into consideration against the BLAKE2 algorithm and not against this library in particular.
A reference function that uses blake2b directly is used to compare against it: this lib can't be faster than that.

Regarding itsdangerous (2.0.1), I found this lib to be marginally faster when compared to it using blake2b, somewhat faster regarding sha256, 384 and 512 and slower regarding sha1.

Regarding django (4.0), I found this lib to be quite faster when compared to it using blake2b, sha256, sha384 and sha512 and slower regarding sha1. Note that its Signer doesn't handle arbitrary bytes well (it breaks raising BadSignature if you use data_b below, so it needs data_s).

Regarding pyjwt (2.3.0), I found this lib to be quite faster when compared to it using blake2b (hack) and sha256 (hs256).

Install requirements

python3 -m pip install blake2signer blake3>=0.2 pyjwt~=2.3 django~=4.0 itsdangerous~=2.0

Note

The standard deviation presented on each evaluation should be at least two orders of magnitude lower than the mean for appropriate results. As a simple reference, for an Intel i7-6820HQ @ 2.70GHz × 8 with 16 GB memory the mean is in ms and the std dev should be in us.

Warning

Careful running these tests under PyPy as-is! My machine froze because the memory was exhausted. Try first with a few executions like -n 10.

Info

To include BLAKE3 in the tests, install the package blake3.

"""Timing comparison.

This will take a while to execute, go grab a coffee or something :)
"""

import json
from hashlib import blake2b
from hashlib import blake2s
from hashlib import sha1
from hashlib import sha256
from hashlib import sha384
from hashlib import sha512
from hmac import compare_digest
from secrets import token_bytes

import jwt
from django.conf import settings
from django.core import signing
from itsdangerous import Signer
from itsdangerous import URLSafeSerializer

from blake2signer import Blake2SerializerSigner
from blake2signer import Blake2Signer
from blake2signer.errors import MissingDependencyError


def format_time(
        dt: float,
        *,
        unit: str = None,
        precision: int = 3,
) -> str:
    """Format time (copied from timeit lib)."""
    units = {'ns': 1e-9, 'us': 1e-6, 'ms': 1e-3, 's': 1.0}

    if unit:
        scale = units[unit]
    else:
        scales = [(scale, unit) for unit, scale in units.items()]
        scales.sort(reverse=True)
        for scale, unit in scales:
            if dt >= scale:
                break

    return '%.*g %s' % (precision, dt / scale, unit)

def print_row(name: str, value: float, ok: bool, baseline: float):
    """Print a table row."""
    rel = int(value * 100 / baseline) - 100
    perf_diff = '' if rel == 0 else ('(slower than baseline)' if rel > 0 else '(faster than baseline)')
    print(
        name.ljust(40),
        '|',
        format_time(value).rjust(13),
        '|',
        ('√' if ok else '⚠').center(7),
        '|',
        f'{rel}%'.rjust(4) if value != baseline else 'baseline',
        perf_diff,
    )


# Hack to get PyJWT with blake2b
jwt_b2 = jwt.PyJWS()
jwt_b2._algorithms.update({
    'HSB2B': jwt.algorithms.HMACAlgorithm(blake2b),
    'HSB2S': jwt.algorithms.HMACAlgorithm(blake2s),
})


def jwt_b2_encode(
        payload: dict,
        key: str,
        algo: str,
) -> str:
    """Hack the JWT encode method."""
    # https://github.com/jpadilla/pyjwt/blob/69d1e8b5f450f2b1df42149d977b48e286df1054/jwt/api_jwt.py#L37
    # Payload
    payload = payload.copy()
    for time_claim in ['exp', 'iat', 'nbf']:
        if payload.get(time_claim):
            pass

    json_payload = json.dumps(payload, separators=(',', ':')).encode('utf-8')

    return jwt_b2.encode(json_payload, key, algo)


def jwt_b2_decode(
        jwt: str,
        key: str,
        algorithms: list = None,
        options: dict = None,
        **kwargs,
):
    """Hack the JWT decode method."""
    # https://github.com/jpadilla/pyjwt/blob/69d1e8b5f450f2b1df42149d977b48e286df1054/jwt/api_jwt.py#L65
    options = {'verify_signature': True}

    if not options['verify_signature']:
        options.setdefault('verify_exp', False)
        options.setdefault('verify_nbf', False)
        options.setdefault('verify_iat', False)
        options.setdefault('verify_aud', False)
        options.setdefault('verify_iss', False)

    if options['verify_signature'] and not algorithms:
        raise ValueError(
            'It is required that you pass in a value for the "algorithms" argument when calling decode().'
        )

    decoded = jwt_b2.decode_complete(
        jwt,
        key=key,
        algorithms=algorithms,
        options=options,
        **kwargs,
    )

    try:
        payload = json.loads(decoded["payload"])
    except ValueError as e:
        raise ValueError("Invalid payload string: %s" % e)
    if not isinstance(payload, dict):
        raise ValueError("Invalid payload string: must be a json object")

    return payload


def blake2b_sign(value: bytes, key: bytes) -> bytes:
    """A basic "singing" function using blake2b to be used as sentinel."""
    salt = token_bytes(blake2b.SALT_SIZE)
    sig = blake2b(value, key=key, salt=salt, digest_size=16).digest()

    return salt + sig + b'.' + value


def blake2b_unsign(signed_data: bytes, key: bytes) -> bytes:
    """A basic "unsinging" function using blake2b to be used as sentinel."""
    salt = signed_data[:blake2b.SALT_SIZE]
    sig = signed_data[blake2b.SALT_SIZE:blake2b.SALT_SIZE + 16]
    value = signed_data[blake2b.SALT_SIZE + 16 + 1:]

    good_sig = blake2b(value, key=key, salt=salt, digest_size=16).digest()

    if compare_digest(good_sig, sig):
        return value

    raise ValueError('signature mismatch')


def blake2s_sign(value: bytes, key: bytes) -> bytes:
    """A basic "singing" function using blake2s to be used as sentinel."""
    salt = token_bytes(blake2s.SALT_SIZE)
    sig = blake2s(value, key=key, salt=salt, digest_size=16).digest()

    return salt + sig + b'.' + value


def blake2s_unsign(signed_data: bytes, key: bytes) -> bytes:
    """A basic "unsinging" function using blake2s to be used as sentinel."""
    salt = signed_data[:blake2s.SALT_SIZE]
    sig = signed_data[blake2s.SALT_SIZE:blake2s.SALT_SIZE + 16]
    value = signed_data[blake2s.SALT_SIZE + 16 + 1:]

    good_sig = blake2s(value, key=key, salt=salt, digest_size=16).digest()

    if compare_digest(good_sig, sig):
        return value

    raise ValueError('signature mismatch')


settings.configure()  # Initialize Django

secret = b'1' * 16

blake2signer = Blake2Signer(secret)
blake2signer_d = Blake2Signer(secret, deterministic=True)
blake2signer_b2s = Blake2Signer(secret, hasher='blake2s')
blake2signer_b2s_d = Blake2Signer(secret, hasher='blake2s', deterministic=True)
itdsigner_b2 = Signer(secret, digest_method=blake2b)
itdsigner_b2s = Signer(secret, digest_method=blake2s)
itdsigner_s1 = Signer(secret, digest_method=sha1)
itdsigner_s256 = Signer(secret, digest_method=sha256)
itdsigner_s384 = Signer(secret, digest_method=sha384)
itdsigner_s512 = Signer(secret, digest_method=sha512)
djsigner_b2 = signing.Signer(secret, algorithm='blake2b')
djsigner_b2s = signing.Signer(secret, algorithm='blake2s')
djsigner_s1 = signing.Signer(secret, algorithm='sha1')
djsigner_s256 = signing.Signer(secret, algorithm='sha256')
djsigner_s384 = signing.Signer(secret, algorithm='sha384')
djsigner_s512 = signing.Signer(secret, algorithm='sha512')
blake2serializer = Blake2SerializerSigner(secret)
blake2serializer_d = Blake2SerializerSigner(secret, deterministic=True)
blake2serializer_b2s = Blake2SerializerSigner(secret, hasher='blake2s')
blake2serializer_b2s_d = Blake2SerializerSigner(secret, hasher='blake2s', deterministic=True)
itdserializer_b2 = URLSafeSerializer(secret, signer_kwargs={'digest_method': blake2b})
itdserializer_b2s = URLSafeSerializer(secret, signer_kwargs={'digest_method': blake2s})

try:
    blake2signer_b3 = Blake2Signer(secret, hasher='blake3')
except MissingDependencyError:
    has_blake3 = False
    print('Note: `blake3` (https://pypi.org/project/blake3) is not installed, BLAKE3 tests disabled')
    print()
else:
    blake2signer_b3_d = Blake2Signer(secret, hasher='blake3', deterministic=True)
    blake2serializer_b3 = Blake2SerializerSigner(secret, hasher='blake3')
    blake2serializer_b3_d = Blake2SerializerSigner(secret, hasher='blake3', deterministic=True)
    has_blake3 = True

# regular and big payloads
for data in ({'payload': [{'a': 'b'}, 1] * 6}, {'payload': [{'a': 'b'}, 1] * 1_000}):
    data_s = json.dumps(data)
    data_b = data_s.encode()
    print('Payload size ~:', len(data_b), 'bytes')

    signers = {}
    serializers = {}

    print('Calculating, please wait (this will take a while)...')
    print()

    # Using ipython:
    print('Blake2Signer(blake2b, determ)')
    signers['Blake2Signer(blake2b, determ)'] = %timeit -o -r 10 blake2signer_d.unsign(blake2signer_d.sign(data_b))
    print()

    print('Blake2Signer(blake2b)')
    signers['Blake2Signer(blake2b)'] = %timeit -o -r 10 blake2signer.unsign(blake2signer.sign(data_b))
    print()

    print('Blake2Signer(blake2s, determ)')
    signers['Blake2Signer(blake2s, determ)'] = %timeit -o -r 10 blake2signer_b2s_d.unsign(blake2signer_b2s_d.sign(data_b))
    print()

    print('Blake2Signer(blake2s)')
    signers['Blake2Signer(blake2s)'] = %timeit -o -r 10 blake2signer_b2s.unsign(blake2signer_b2s.sign(data_b))
    print()

    if has_blake3:
        print('Blake2Signer(blake3, determ)')
        signers['Blake2Signer(blake3, determ)'] = %timeit -o -r 10 blake2signer_b3_d.unsign(blake2signer_b3_d.sign(data_b))
        print()

        print('Blake2Signer(blake3)')
        signers['Blake2Signer(blake3)'] = %timeit -o -r 10 blake2signer_b3.unsign(blake2signer_b3.sign(data_b))
        print()

    print('Blake2b(sentinel)')
    signers['Blake2(sentinel)'] = %timeit -o -r 10 blake2b_unsign(blake2b_sign(data_b, secret), secret)
    print()

    print('Blake2s(sentinel)')
    signers['Blake2s(sentinel)'] = %timeit -o -r 10 blake2s_unsign(blake2s_sign(data_b, secret), secret)
    print()

    print('ItsDangerousSigner(blake2b)')
    signers['ItsDangerousSigner(blake2b)'] = %timeit -o -r 10 itdsigner_b2.unsign(itdsigner_b2.sign(data_b))
    print()

    print('ItsDangerousSigner(blake2s)')
    signers['ItsDangerousSigner(blake2s)'] = %timeit -o -r 10 itdsigner_b2s.unsign(itdsigner_b2s.sign(data_b))
    print()

    print('ItsDangerousSigner(sha1)')
    signers['ItsDangerousSigner(sha1)'] = %timeit -o -r 10 itdsigner_s1.unsign(itdsigner_s1.sign(data_b))
    print()

    print('ItsDangerousSigner(sha256)')
    signers['ItsDangerousSigner(sha256)'] = %timeit -o -r 10 itdsigner_s256.unsign(itdsigner_s256.sign(data_b))
    print()

    print('ItsDangerousSigner(sha384)')
    signers['ItsDangerousSigner(sha384)'] = %timeit -o -r 10 itdsigner_s384.unsign(itdsigner_s384.sign(data_b))
    print()

    print('ItsDangerousSigner(sha512)')
    signers['ItsDangerousSigner(sha512)'] = %timeit -o -r 10 itdsigner_s512.unsign(itdsigner_s512.sign(data_b))
    print()

    print('DjangoSigner(blake2b)')
    signers['DjangoSigner(blake2b)'] = %timeit -o -r 10 djsigner_b2.unsign(djsigner_b2.sign(data_s))
    print()

    print('DjangoSigner(blake2s)')
    signers['DjangoSigner(blake2s)'] = %timeit -o -r 10 djsigner_b2s.unsign(djsigner_b2s.sign(data_s))
    print()

    print('DjangoSigner(sha1)')
    signers['DjangoSigner(sha1)'] = %timeit -o -r 10 djsigner_s1.unsign(djsigner_s1.sign(data_s))
    print()

    print('DjangoSigner(sha256)')
    signers['DjangoSigner(sha256)'] = %timeit -o -r 10 djsigner_s256.unsign(djsigner_s256.sign(data_s))
    print()

    print('DjangoSigner(sha384)')
    signers['DjangoSigner(sha384)'] = %timeit -o -r 10 djsigner_s384.unsign(djsigner_s384.sign(data_s))
    print()

    print('DjangoSigner(sha512)')
    signers['DjangoSigner(sha512)'] = %timeit -o -r 10 djsigner_s512.unsign(djsigner_s512.sign(data_s))
    print()

    print('Blake2SerializerSigner(blake2b, determ)')
    serializers['Blake2SerializerSigner(blake2b, determ)'] = %timeit -o -r 10 blake2serializer_d.loads(blake2serializer_d.dumps(data))
    print()

    print('Blake2SerializerSigner(blake2b)')
    serializers['Blake2SerializerSigner(blake2b)'] = %timeit -o -r 10 blake2serializer.loads(blake2serializer.dumps(data))
    print()

    print('Blake2SerializerSigner(blake2s, determ)')
    serializers['Blake2SerializerSigner(blake2s, determ)'] = %timeit -o -r 10 blake2serializer_b2s_d.loads(blake2serializer_b2s_d.dumps(data))
    print()

    print('Blake2SerializerSigner(blake2s)')
    serializers['Blake2SerializerSigner(blake2s)'] = %timeit -o -r 10 blake2serializer_b2s.loads(blake2serializer_b2s.dumps(data))
    print()

    if has_blake3:
        print('Blake2SerializerSigner(blake3, determ)')
        serializers['Blake2SerializerSigner(blake3, determ)'] = %timeit -o -r 10 blake2serializer_b3_d.loads(blake2serializer_b3_d.dumps(data))
        print()

        print('Blake2SerializerSigner(blake3)')
        serializers['Blake2SerializerSigner(blake3)'] = %timeit -o -r 10 blake2serializer_b3.loads(blake2serializer_b3.dumps(data))
        print()

    print('ItsDangerousURLSafeSerializer(blake2b)')
    serializers['ItsDangerousURLSafeSerializer(blake2b)'] = %timeit -o -r 10 itdserializer_b2.loads(itdserializer_b2.dumps(data))
    print()

    print('ItsDangerousURLSafeSerializer(blake2s)')
    serializers['ItsDangerousURLSafeSerializer(blake2s)'] = %timeit -o -r 10 itdserializer_b2s.loads(itdserializer_b2s.dumps(data))
    print()

    print('DjangoSerializer(sha256)')
    serializers['DjangoSerializer(sha256)'] = %timeit -o -r 10 signing.loads(signing.dumps(data, key=secret, compress=True), key=secret)
    print()

    print('PyJWTSerializer(sha256)')
    serializers['PyJWTSerializer(sha256)'] = %timeit -o -r 10 jwt.decode(jwt.encode(data, secret, algorithm='HS256'), secret, algorithms=['HS256'])
    print()

    print('PyJWTSerializer(blake2b)')
    serializers['PyJWTSerializer(blake2b)'] = %timeit -o -r 10 jwt_b2_decode(jwt_b2_encode(data, secret, 'HSB2B'), secret, algorithms=['HSB2B'])
    print()

    print('PyJWTSerializer(blake2s)')
    serializers['PyJWTSerializer(blake2s)'] = %timeit -o -r 10 jwt_b2_decode(jwt_b2_encode(data, secret, 'HSB2S'), secret, algorithms=['HSB2S'])
    print()

    print('Signer'.ljust(40), '| Best Abs Time | Measure | Comparison')
    print('-' * 40, '|', '-' * 13, '|', '-' * 7, '|', '-' * 27)
    baseline = signers['Blake2Signer(blake2b, determ)'].best
    for timing in signers:
        ok = (signers[timing].best / signers[timing].stdev) > 60
        print_row(timing, signers[timing].best, ok, baseline)

    print()
    print('Serializer'.ljust(40), '| Best Abs Time | Measure | Comparison')
    print('-' * 40, '|', '-' * 13, '|', '-' * 7, '|', '-' * 27)
    baseline = serializers['Blake2SerializerSigner(blake2b)'].best
    for timing in serializers:
        ok = (serializers[timing].best / serializers[timing].stdev) > 60
        print_row(timing, serializers[timing].best, ok, baseline)

    print()
Back to top