Usage Examples

The following is a simple sample code using PySETO:

>>> import pyseto
>>> from pyseto import Key
>>> private_key_pem = b"-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEILTL+0PfTOIQcn2VPkpxMwf6Gbt9n4UEFDjZ4RuUKjd0\n-----END PRIVATE KEY-----"
>>> public_key_pem = b"-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAHrnbu7wEfAP9cGBOAHHwmH4Wsot1ciXBHwBBXQ4gsaI=\n-----END PUBLIC KEY-----"
>>> private_key = Key.new(version=4, type="public", key=private_key_pem)
>>> token = pyseto.encode(
...     private_key,
...     b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}',
... )
>>> token
B'v4.public.eyJkYXRhIjogInRoaXMgaXMgYSBzaWduZWQgbWVzc2FnZSIsICJleHAiOiAiMjAyMi0wMS0wMVQwMDowMDowMCswMDowMCJ9l1YiKei2FESvHBSGPkn70eFO1hv3tXH0jph1IfZyEfgm3t1DjkYqD5r4aHWZm1eZs_3_bZ9pBQlZGp0DPSdzDg'
>>> public_key = Key.new(version=4, type="public", key=public_key_pem)
>>> decoded = pyseto.decode(public_key, token)
>>> decoded.payload
B'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'

This page shows various examples to use PySETO.

v4.public

Asymmetric Authentication (Public-Key Signatures) with Ed25519 (EdDSA over Curve25519).

You can create an Ed25519 key pair by using openssl as follows:

$ openssl genpkey -algorithm ed25519 -out private_key.pem
$ openssl pkey -in private_key.pem -pubout -out public_key.pem

Use the key pair to generate and consume v4.public PASETO tokens as follows:

import pyseto
from pyseto import Key

with open("./private_key.pem") as key_file:
    private_key = Key.new(4, "public", key_file.read())
token = pyseto.encode(
    private_key,
    payload=b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}',
    footer=b"This is a footer",  # Optional
    implicit_assertion=b"xyz",  # Optional
)

with open("./public_key.pem") as key_file:
    public_key = Key.new(4, "public", key_file.read())
decoded = pyseto.decode(public_key, token, implicit_assertion=b"xyz")

assert (
    decoded.payload
    == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
)
assert decoded.footer == b"This is a footer"
assert decoded.version == "v4"
assert decoded.purpose == "public"

v4.local

Symmetric Authenticated Encryption with AES-256-CTR + HMAC-SHA384 (Encrypt-then-MAC).

import pyseto
from pyseto import Key

key = Key.new(version=4, type="local", key=b"our-secret")
token = pyseto.encode(
    key,
    payload=b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}',
    footer=b"This is a footer",  # Optional
    implicit_assertion=b"xyz",  # Optional
)

decoded = pyseto.decode(key, token, implicit_assertion=b"xyz")

assert (
    decoded.payload
    == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
)
assert decoded.footer == b"This is a footer"
assert decoded.version == "v4"
assert decoded.purpose == "local"

v3.public

Asymmetric Authentication (Public-Key Signatures) with ECDSA over NIST P-384, with SHA-384, using RFC 6979 deterministic k-values.

You can create an ECDSA over NIST P-384 key pair by using openssl as follows:

$ openssl ecparam -genkey -name secp384r1 -noout -out private_key.pem
$ openssl ec -in private_key.pem -pubout -out public_key.pem

Use the key pair to generate and consume v3.public PASETO tokens as follows:

import pyseto
from pyseto import Key

with open("./private_key.pem") as key_file:
    private_key = Key.new(3, "public", key_file.read())
token = pyseto.encode(
    private_key,
    payload=b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}',
    footer=b"This is a footer",  # Optional
    implicit_assertion=b"xyz",  # Optional
)

with open("./public_key.pem") as key_file:
    public_key = Key.new(3, "public", key_file.read())
decoded = pyseto.decode(public_key, token, implicit_assertion=b"xyz")

assert (
    decoded.payload
    == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
)
assert decoded.footer == b"This is a footer"
assert decoded.version == "v3"
assert decoded.purpose == "public"

v3.local

Symmetric Authenticated Encryption with AES-256-CTR + HMAC-SHA384 (Encrypt-then-MAC).

import pyseto
from pyseto import Key

key = Key.new(version=3, type="local", key=b"our-secret")
token = pyseto.encode(
    key,
    payload=b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}',
    footer=b"This is a footer",  # Optional
    implicit_assertion=b"xyz",  # Optional
)

decoded = pyseto.decode(key, token, implicit_assertion=b"xyz")

assert (
    decoded.payload
    == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
)
assert decoded.footer == b"This is a footer"
assert decoded.version == "v3"
assert decoded.purpose == "local"

v2.public

Asymmetric Authentication (Public-Key Signatures) with Ed25519.

Create an Ed25519 key pair by using openssl as follows:

$ openssl genpkey -algorithm ed25519 -out private_key.pem
$ openssl pkey -in private_key.pem -pubout -out public_key.pem

Use the key pair to generate and consume v2.public PASETO tokens as follows:

import pyseto
from pyseto import Key

with open("./private_key.pem") as key_file:
    private_key = Key.new(2, "public", key_file.read())
token = pyseto.encode(
    private_key,
    payload=b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}',
    footer=b"This is a footer",  # Optional
)

with open("./public_key.pem") as key_file:
    public_key = Key.new(2, "public", key_file.read())
decoded = pyseto.decode(public_key, token)

assert (
    decoded.payload
    == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
)
assert decoded.footer == b"This is a footer"
assert decoded.version == "v2"
assert decoded.purpose == "public"

v2.local

Symmetric Authenticated Encryption with XChaCha20-Poly1305 (192-bit nonce, 256-bit key and 128-bit authentication tag).

In this case, you must use 32 byte key as follows:

import pyseto
from pyseto import Key
from secrets import token_bytes

key = Key.new(version=2, type="local", key=token_bytes(32))
token = pyseto.encode(
    key,
    payload=b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}',
    footer=b"This is a footer",  # Optional
)

decoded = pyseto.decode(key, token)

assert (
    decoded.payload
    == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
)
assert decoded.footer == b"This is a footer"
assert decoded.version == "v2"
assert decoded.purpose == "local"

v1.public

Asymmetric Authentication (Public-Key Signatures) with RSASSA-PSS 2048-bit key, SHA384 hashing and MGF1+SHA384.

Create an RSA key pair by using openssl as follows:

$ openssl genrsa -out private_key.pem 2048
$ openssl rsa -in private_key.pem -outform PEM -pubout -out public_key.pem

Use the key pair to generate and consume v1.public PASETO tokens as follows:

import pyseto
from pyseto import Key

with open("./private_key.pem") as key_file:
    private_key = Key.new(1, "public", key_file.read())
token = pyseto.encode(
    private_key,
    payload=b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}',
    footer=b"This is a footer",  # Optional
)

with open("./public_key.pem") as key_file:
    public_key = Key.new(1, "public", key_file.read())
decoded = pyseto.decode(public_key, token)

assert (
    decoded.payload
    == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
)
assert decoded.footer == b"This is a footer"
assert decoded.version == "v1"
assert decoded.purpose == "public"

v1.local

Symmetric Authenticated Encryption with AES-256-CTR + HMAC-SHA384 (Encrypt-then-MAC).

import pyseto
from pyseto import Key
from secrets import token_bytes

key = Key.new(version=1, type="local", key=b"our-secret")
token = pyseto.encode(
    key,
    payload=b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}',
    footer=b"This is a footer",  # Optional
)

decoded = pyseto.decode(key, token)

assert (
    decoded.payload
    == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
)
assert decoded.footer == b"This is a footer"
assert decoded.version == "v1"
assert decoded.purpose == "local"