PySETO
PySETO is a Python implementation of PASETO (Platform-Agnostic SEcurity TOkens) and PASERK (Platform-Agnostic Serialized Keys). It supports all PASETO versions (v1, v2, v3, and v4) and purposes (local and public), having passed all official tests. The library is currently at version 1.9.1 and maintains a regular release cadence.
Common errors
-
ERROR: Cannot install pyopenssl==X.Y.Z and pyseto==A.B.C because these package versions have conflicting dependencies.
cause Conflicting strict version requirements for a shared dependency (e.g., `cryptography` or `pycryptodomex`) between `pyseto` and another installed library (like `pyopenssl`).fixTry updating `pyseto` to the latest version. If the error persists, attempt to install specific versions of `pyopenssl` and `pyseto` that have compatible `cryptography` or `pycryptodomex` requirements. Consult the `setup.py` or `pyproject.toml` of both packages for their exact dependency specifications. Using a dedicated virtual environment for each project can prevent such conflicts. -
NameError: name 'Key' is not defined
cause The `Key` class, used for creating PASETO keys, was not imported explicitly from the `pyseto` package.fixAdd `from pyseto import Key` at the top of your Python file where `Key` is used. -
pyseto.exceptions.DecryptError: Failed to decrypt the message
cause This error occurs during `pyseto.decode()` when attempting to decrypt a `local` PASETO token if the provided symmetric key is incorrect, or if the token has been tampered with.fixEnsure the correct symmetric key is used for decryption. Verify that the token itself has not been altered or corrupted. For `public` tokens, a `VerifyError` would typically indicate a signature mismatch. -
pyseto.exceptions.VerifyError: Failed to verify the message
cause This error occurs during `pyseto.decode()` when attempting to verify a `public` PASETO token if the provided public key does not match the private key used for signing, or if the token's signature has been tampered with.fixEnsure the correct public key (corresponding to the private key used for signing) is provided for verification. Validate the integrity of the token and ensure it has not been modified after creation.
Warnings
- breaking Earlier versions of PySETO (e.g., <1.8.0) used strict version pinning for core dependencies like `cryptography` and `pycryptodomex`. This could lead to `ResolutionImpossible` errors during installation when combined with other libraries that had different `cryptography` requirements (e.g., `pyopenssl`).
- deprecated PASETO v2 is expected to be deprecated in the PASETO standard due to underlying cryptographic primitives. While PySETO supports v2, new development should ideally target PASETO versions 3 or 4 for future compatibility and enhanced security.
- gotcha The top-level `pyseto.encode()` and `pyseto.decode()` functions are aliases to `encode()` and `decode()` methods of a global `Paseto` class instance created with default settings. If you intend to use custom `Paseto` instance settings (e.g., different default expiration times or `iat` inclusion), you must instantiate `Paseto` directly and call its methods, rather than relying on `pyseto.encode/decode`.
Install
-
pip install pyseto
Imports
- pyseto
import pyseto
- Key
import Key
from pyseto import Key
Quickstart
import os
import pyseto
from pyseto import Key
# --- Example for v4.public (Asymmetric Signature) ---
# In a real application, keys should be loaded securely, e.g., from environment variables or a KMS.
# For demonstration, we use hardcoded keys. DO NOT USE IN PRODUCTION AS IS.
# These PEMs are for Ed25519 (v4.public)
private_key_pem = os.environ.get(
'PSETO_V4_PRIVATE_KEY_PEM',
b"""-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEILTL+0PfTOIQcn2VPkpxMwf6Gbt9n4UEFDjZ4RuUKjd0
-----END PRIVATE KEY-----
""").encode('utf-8')
public_key_pem = os.environ.get(
'PSETO_V4_PUBLIC_KEY_PEM',
b"""-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEAHrnbu7wEfAP9cGBOAHHwmH4Wsot1ciXBHwBBXQ4gsaI=
-----END PUBLIC KEY-----
""").encode('utf-8')
# 1. Create a private key for signing
private_key = Key.new(version=4, purpose="public", key=private_key_pem)
# 2. Encode/Sign a PASETO token
payload = {"data": "this is a signed message", "user_id": "123"}
footer = {"kid": "v4-public-key-001"}
token = pyseto.encode(private_key, payload, footer=footer, serializer=pyseto.json_serializer)
print(f"Generated Token: {token.decode()}")
# 3. Create a public key for verification
public_key = Key.new(version=4, purpose="public", key=public_key_pem)
# 4. Decode and verify the token
decoded_token = pyseto.decode(public_key, token, deserializer=pyseto.json_deserializer)
# The payload and footer are accessible as dictionary-like objects if deserializer is used
print(f"Decoded Payload: {decoded_token.payload}")
print(f"Decoded Footer: {decoded_token.footer}")
assert decoded_token.payload['data'] == "this is a signed message"
assert decoded_token.footer['kid'] == "v4-public-key-001"
print("Token verified successfully!")