summaryrefslogtreecommitdiff
path: root/python-pyseto.spec
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2023-05-17 04:35:11 +0000
committerCoprDistGit <infra@openeuler.org>2023-05-17 04:35:11 +0000
commitb187ef3f4477180ac2a5d110f32fecb87d0be64d (patch)
tree343c7d09261b345f6021e4ef6d28b3f800fa17b4 /python-pyseto.spec
parentcbd80d4db4d8086d24bad747b93479057599963c (diff)
automatic import of python-pyseto
Diffstat (limited to 'python-pyseto.spec')
-rw-r--r--python-pyseto.spec1249
1 files changed, 1249 insertions, 0 deletions
diff --git a/python-pyseto.spec b/python-pyseto.spec
new file mode 100644
index 0000000..1d698a7
--- /dev/null
+++ b/python-pyseto.spec
@@ -0,0 +1,1249 @@
+%global _empty_manifest_terminate_build 0
+Name: python-pyseto
+Version: 1.7.2
+Release: 1
+Summary: A Python implementation of PASETO/PASERK.
+License: MIT
+URL: https://github.com/dajiaji/pyseto
+Source0: https://mirrors.nju.edu.cn/pypi/web/packages/37/b4/abb49bf0815b26870ceedf6dd4e557b87f58fabc43806e8c41d1412c2aa7/pyseto-1.7.2.tar.gz
+BuildArch: noarch
+
+Requires: python3-cryptography
+Requires: python3-pycryptodomex
+Requires: python3-passlib[argon2]
+Requires: python3-iso8601
+Requires: python3-Sphinx[docs]
+Requires: python3-sphinx-autodoc-typehints[docs]
+Requires: python3-sphinx-rtd-theme[docs]
+
+%description
+# PySETO - A Python implementation of PASETO/PASERK
+
+[![PyPI version](https://badge.fury.io/py/pyseto.svg)](https://badge.fury.io/py/pyseto)
+![PyPI - Python Version](https://img.shields.io/pypi/pyversions/pyseto)
+[![Documentation Status](https://readthedocs.org/projects/pyseto/badge/?version=latest)](https://pyseto.readthedocs.io/en/latest/?badge=latest)
+![Github CI](https://github.com/dajiaji/pyseto/actions/workflows/python-package.yml/badge.svg)
+[![codecov](https://codecov.io/gh/dajiaji/pyseto/branch/main/graph/badge.svg?token=QN8GXEYEP3)](https://codecov.io/gh/dajiaji/pyseto)
+
+
+PySETO is a [PASETO (Platform-Agnostic SEcurity TOkens)](https://paseto.io/)/[PASERK (Platform-Agnostic Serialized Keys)](https://github.com/paseto-standard/paserk) implementation written in Python
+which supports all of the versions ([v1](https://github.com/paseto-standard/paseto-spec/blob/master/docs/01-Protocol-Versions/Version1.md),
+[v2](https://github.com/paseto-standard/paseto-spec/blob/master/docs/01-Protocol-Versions/Version2.md),
+[v3](https://github.com/paseto-standard/paseto-spec/blob/master/docs/01-Protocol-Versions/Version3.md) and
+[v4](https://github.com/paseto-standard/paseto-spec/blob/master/docs/01-Protocol-Versions/Version4.md)) and purposes (`public` and `local`)
+and has passed all of [the official tests](https://github.com/paseto-standard/test-vectors).
+
+You can install PySETO with pip:
+
+```sh
+$ pip install pyseto
+```
+
+PySETO can be used in ease as follows (in case of `v4.public`):
+
+```py
+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-----"
+
+
+# Create a PASETO token.
+private_key = Key.new(version=4, purpose="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"}')
+
+# Decode and verify a PASETO token.
+public_key = Key.new(version=4, purpose="public", key=public_key_pem)
+decoded = pyseto.decode(public_key, token)
+
+assert token == b'v4.public.eyJkYXRhIjogInRoaXMgaXMgYSBzaWduZWQgbWVzc2FnZSIsICJleHAiOiAiMjAyMi0wMS0wMVQwMDowMDowMCswMDowMCJ9l1YiKei2FESvHBSGPkn70eFO1hv3tXH0jph1IfZyEfgm3t1DjkYqD5r4aHWZm1eZs_3_bZ9pBQlZGp0DPSdzDg'
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+```
+
+See following contents or [Documentation](https://pyseto.readthedocs.io/en/stable/) for details.
+
+## Index
+
+- [Installation](#installation)
+- [Supported PASETO Versions](#supported-paseto-versions)
+- [Supported PASERK Types](#supported-paserk-types)
+- [PASETO Usage](#paseto-usage)
+ - [Basic usage: v4.public](#basic-usage-v4public)
+ - [Basic usage: v4.local](#basic-usage-v4local)
+ - [Using serializer/deserializer for payload and footer](#using-serializerdeserializer-for-payload-and-footer)
+ - [Using Paseto class for handling registered claims](#using-paseto-class-for-handling-registered-claims)
+- [PASERK Usage](#paserk-usage)
+ - [Serializing/Deserializing PASERK](#serializingdeserializing-paserk)
+ - [Serializing PASERK ID](#serializing-paserk-id)
+ - [Key Wrapping](#key-wrapping)
+ - [Password-based Key Encryption](#password-based-key-encryption)
+ - [Asymmetric Encryption](#asymmetric-encryption)
+- [API Reference](#api-reference)
+- [Tests](#tests)
+- [Contributing](#contributing)
+
+## Installation
+
+You can install PySETO with pip:
+
+```sh
+$ pip install pyseto
+```
+
+## Supported PASETO Versions
+
+PySETO supports all of PASETO versions and purposes below:
+
+
+| | v4 | v3 | v2 | v1 |
+| ---------| ---- | ---- | ---- | ---- |
+| `local` | ✅ | ✅ | ✅ | ✅ |
+| `public` | ✅ | ✅ | ✅ | ✅ |
+
+
+## Supported PASERK Types
+
+PySETO also supports [PASERK (Platform-Agnostic Serialized Keys)](https://github.com/paseto-standard/paserk).
+Currently, following PASERK types are supported:
+
+
+| | v4 | v3 | v2 | v1 |
+| ------------- | ---- | ---- | ---- | ---- |
+| `lid` | ✅ | ✅ | ✅ | ✅ |
+| `sid` | ✅ | ✅ | ✅ | ✅ |
+| `pid` | ✅ | ✅ | ✅ | ✅ |
+| `local` | ✅ | ✅ | ✅ | ✅ |
+| `secret` | ✅ | ✅ | ✅ | ✅ |
+| `public` | ✅ | ✅ | ✅ | ✅ |
+| `seal` | ✅ | | ✅ | |
+| `local-wrap` | ✅ | ✅ | ✅ | ✅ |
+| `secret-wrap` | ✅ | ✅ | ✅ | ✅ |
+| `local-pw` | ✅ | ✅ | ✅ | ✅ |
+| `secret-pw` | ✅ | ✅ | ✅ | ✅ |
+
+
+## PASETO Usage
+
+By using this PySETO, you can easily create, decode and verify PASETO tokens. Here are sample codes that handle version 4 PySETO tokens.
+
+Please refer to [the Documentation](https://pyseto.readthedocs.io/en/stable/) for all usage examples including other versions.
+
+### Basic usage: v4.public
+
+`v4.public` is one of current PASETO versions to be used for asymmetric authentication (public key signatures).
+
+```py
+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, purpose="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"}')
+
+public_key = Key.new(version=4, purpose="public", key=public_key_pem)
+decoded = pyseto.decode(public_key, token)
+
+assert token == b'v4.public.eyJkYXRhIjogInRoaXMgaXMgYSBzaWduZWQgbWVzc2FnZSIsICJleHAiOiAiMjAyMi0wMS0wMVQwMDowMDowMCswMDowMCJ9l1YiKei2FESvHBSGPkn70eFO1hv3tXH0jph1IfZyEfgm3t1DjkYqD5r4aHWZm1eZs_3_bZ9pBQlZGp0DPSdzDg'
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+```
+
+### Basic usage: v4.local
+
+`v4.local` is one of current PASETO versions to be used for symmetric authenticated encryption.
+
+```py
+import pyseto
+from pyseto import Key
+
+key = Key.new(version=4, purpose="local", key=b"our-secret")
+token = pyseto.encode(key, b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}')
+
+decoded = pyseto.decode(key, token)
+
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+```
+
+### Using serializer/deserializer for payload and footer
+
+By using `serializer` and `deserializer`, you can encode/decode a dict-typed payload and footer included in PASETO tokens into an arbitrary format.
+The following example shows that the payload and the footer in a PASETO token are encoded/decoded as JSON formatted data.
+When specifing dict-typed payload, exp parameter can be used to set the expiration time (seconds) of the token.
+
+```py
+import json
+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, purpose="public", key=private_key_pem)
+public_key = Key.new(version=4, purpose="public", key=public_key_pem)
+token = pyseto.encode(
+ private_key,
+ {"data": "this is a signed message"},
+ footer={"kid": public_key.to_paserk_id()},
+ serializer=json,
+ exp=3600,
+)
+
+decoded = pyseto.decode(public_key, token, deserializer=json)
+
+assert decoded.payload["data"] == "this is a signed message"
+assert decoded.payload["exp"] == "2021-11-11T00:00:00+00:00"
+assert decoded.footer["kid"] == "k4.pid.yh4-bJYjOYAG6CWy0zsfPmpKylxS7uAWrxqVmBN2KAiJ"
+```
+
+### Using `Paseto` class for handling registered claims
+
+By using `Paseto` class, you can change the default value of `exp` (the expiration date ot tokens), whether to include an `iat` claim, and other settings.
+
+Note that `pyseto.encode()` and `pyseto.decode()` are aliases to the `encode()` and `decode()` of the global "Paseto" class instance created with the default settings.
+
+```py
+import json
+import pyseto
+from pyseto import Key, Paseto
+
+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, purpose="public", key=private_key_pem)
+paseto = Paseto.new(exp=3600, include_iat=True) # Default values are exp=0(not specified) and including_iat=False
+token = paseto.encode(
+ private_key,
+ {"data": "this is a signed message"},
+ serializer=json,
+)
+
+public_key = Key.new(version=4, purpose="public", key=public_key_pem)
+decoded = pyseto.decode(public_key, token, deserializer=json)
+
+assert decoded.payload["data"] == "this is a signed message"
+assert decoded.payload["iat"] == "2021-11-11T00:00:00+00:00"
+assert decoded.payload["exp"] == "2021-11-11T01:00:00+00:00"
+```
+
+## PASERK Usage
+
+[PASERK (Platform-Agnostic Serialized Keys)](https://github.com/paseto-standard/paserk) is an extension to PASETO that provides key-wrapping and serialization.
+
+### Serializing/Deserializing PASERK
+
+As shown in the examples above, the `pyseto.Key` used for encryption and signature can be generated from PASERK or converted to PASERK as follows:
+
+```py
+import pyseto
+from pyseto import Key
+
+# pyseto.Key can be generated from PASERK.
+symmetric_key = Key.new(version=4, purpose="local", key=b"our-secret")
+private_key = Key.from_paserk("k4.secret.tMv7Q99M4hByfZU-SnEzB_oZu32fhQQUONnhG5QqN3Qeudu7vAR8A_1wYE4AcfCYfhayi3VyJcEfAEFdDiCxog")
+public_key = Key.from_paserk("k4.public.Hrnbu7wEfAP9cGBOAHHwmH4Wsot1ciXBHwBBXQ4gsaI")
+
+token = pyseto.encode(private_key, b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}')
+decoded = pyseto.decode(public_key, token)
+
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+
+# PASERK can be derived from pyseto.Key.
+assert symmetric_key.to_paserk() == "k4.local.b3VyLXNlY3JldA"
+assert private_key.to_paserk() == "k4.secret.tMv7Q99M4hByfZU-SnEzB_oZu32fhQQUONnhG5QqN3Qeudu7vAR8A_1wYE4AcfCYfhayi3VyJcEfAEFdDiCxog"
+assert public_key.to_paserk() == "k4.public.Hrnbu7wEfAP9cGBOAHHwmH4Wsot1ciXBHwBBXQ4gsaI"
+```
+
+### Serializing PASERK ID
+
+`pyseto.Key` can also be converted to PASERK ID as follows:
+
+```py
+import pyseto
+from pyseto import Key
+
+# pyseto.Key can be generated from PASERK.
+symmetric_key = Key.new(version=4, purpose="local", key=b"our-secret")
+private_key = Key.from_paserk("k4.secret.tMv7Q99M4hByfZU-SnEzB_oZu32fhQQUONnhG5QqN3Qeudu7vAR8A_1wYE4AcfCYfhayi3VyJcEfAEFdDiCxog")
+public_key = Key.from_paserk("k4.public.Hrnbu7wEfAP9cGBOAHHwmH4Wsot1ciXBHwBBXQ4gsaI")
+
+# PASERK ID can be derived from pyseto.Key.
+assert symmetric_key.to_paserk_id() == "k4.lid._D6kgTzxgiPGk35gMj9bukgj4En2H94u22wVX9zaoh05"
+assert private_key.to_paserk() == "k4.secret.tMv7Q99M4hByfZU-SnEzB_oZu32fhQQUONnhG5QqN3Qeudu7vAR8A_1wYE4AcfCYfhayi3VyJcEfAEFdDiCxog"
+assert public_key.to_paserk_id() == "k4.pid.yh4-bJYjOYAG6CWy0zsfPmpKylxS7uAWrxqVmBN2KAiJ"
+```
+
+### Key Wrapping
+
+If you call `to_paserk` with `wrapping_key`, you can get a wrapped (encrypted) PASERK with the wrapping key.
+The wrapped PASERK can be decrypted by calling `from_paserk` with `wrapping key`.
+
+In case of `local-wrap.pie`:
+
+```py
+import pyseto
+from pyseto import Key
+
+raw_key = Key.new(version=4, purpose="local", key=b"our-secret")
+wrapping_key = token_bytes(32)
+wpk = raw_key.to_paserk(wrapping_key=wrapping_key)
+token = pyseto.encode(raw_key, b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}')
+
+unwrapped_key = Key.from_paserk(wpk, wrapping_key=wrapping_key)
+decoded = pyseto.decode(unwrapped_key, token)
+
+# assert wpk == "k4.local-wrap.pie.TNKEwC4K1xBcgJ_GiwWAoRlQFE33HJO3oN9DHEZ05pieSCd-W7bgAL64VG9TZ_pBkuNBFHNrfOGHtnfnhYGdbz5-x3CxShhPJxg"
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+```
+
+In case of `secret-wrap.pie`:
+
+```py
+import pyseto
+from pyseto import Key
+
+raw_private_key = Key.from_paserk(
+ "k4.secret.tMv7Q99M4hByfZU-SnEzB_oZu32fhQQUONnhG5QqN3Qeudu7vAR8A_1wYE4AcfCYfhayi3VyJcEfAEFdDiCxog"
+)
+wrapping_key = token_bytes(32)
+wpk = raw_private_key.to_paserk(wrapping_key=wrapping_key)
+unwrapped_private_key = Key.from_paserk(wpk, wrapping_key=wrapping_key)
+token = pyseto.encode(unwrapped_private_key, b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}')
+
+public_key = Key.from_paserk("k4.public.Hrnbu7wEfAP9cGBOAHHwmH4Wsot1ciXBHwBBXQ4gsaI")
+decoded = pyseto.decode(public_key, token)
+
+# assert wpk == "k4.secret-wrap.pie.excv7V4-NaECy5hpji-tkSkMvyjsAgNxA-mGALgdjyvGNyDlTb89bJ35R1e3tILgbMpEW5WXMXzySe2T-sBz-ZAcs1j7rbD3ZWvsBTM6K5N9wWfAxbR4ppCXH_H5__9yY-kBaF2NimyAJyduhOhSmqLm6TTSucpAOakEJOXePW8"
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+```
+
+### Password-based Key Encryption
+
+If you call `to_paserk` with `password`, you can get a wrapped (encrypted) PASERK with the password.
+The wrapped PASERK can be decrypted by calling `from_paserk` with `passwrod`.
+
+In case of `local-pw`:
+
+```py
+import pyseto
+from pyseto import Key
+
+raw_key = Key.new(version=4, purpose="local", key=b"our-secret")
+token = pyseto.encode(raw_key, b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}')
+
+wpk = raw_key.to_paserk(password="our-secret")
+unwrapped_key = Key.from_paserk(wpk, password="our-secret")
+decoded = pyseto.decode(unwrapped_key, token)
+
+# assert wpk == "k4.local-pw.HrCs9Pu-2LB0l7jkHB-x2gAAAAAA8AAAAAAAAgAAAAGttW0IHZjQCHJdg-Vc3tqO_GSLR4vzLl-yrKk2I-l8YHj6jWpC0lQB2Z7uzTtVyV1rd_EZQPzHdw5VOtyucP0FkCU"
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+```
+
+In case of `secret-pw`:
+
+```py
+import pyseto
+from pyseto import Key
+
+raw_private_key = Key.from_paserk(
+ "k4.secret.tMv7Q99M4hByfZU-SnEzB_oZu32fhQQUONnhG5QqN3Qeudu7vAR8A_1wYE4AcfCYfhayi3VyJcEfAEFdDiCxog"
+)
+wpk = raw_private_key.to_paserk(password="our-secret")
+unwrapped_private_key = Key.from_paserk(wpk, password="our-secret")
+token = pyseto.encode(unwrapped_private_key, b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}')
+
+public_key = Key.from_paserk(
+ "k4.public.Hrnbu7wEfAP9cGBOAHHwmH4Wsot1ciXBHwBBXQ4gsaI"
+)
+decoded = pyseto.decode(public_key, token)
+
+# assert wpk == "k4.secret-pw.MEMW4K1MaD5nWigCLyEyFAAAAAAA8AAAAAAAAgAAAAFU-tArtryNVjS2n2hCYiM11V6tOyuIog69Bjb0yNZanrLJ3afGclb3kPzQ6IhK8ob9E4QgRdEALGWCizZ0RCPFF_M95IQDfmdYKC0Er656UgKUK4UKG9JlxP4o81UwoJoZYz_D1zTlltipEa5RiNvUtNU8vLKoGSY"
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+```
+
+### Asymmetric Encryption
+
+At this time, PySETO supports asymmetric encryption (key sealing) for `v2` and `v4`.
+
+```py
+import pyseto
+from pyseto import Key
+
+private_key_pem = b"-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VuBCIEIFAF7jSCZHFgWvC8hUkXr55Az6Pot2g4zOAUxck0/6x8\n-----END PRIVATE KEY-----"
+public_key_pem = b"-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VuAyEAFv8IXsICYj0paznDK/99GyCsFOIGnfY87ayyNSIvSB4=\n-----END PUBLIC KEY-----"
+
+raw_key = Key.new(version=4, purpose="local", key=b"our-secret")
+token = pyseto.encode(
+ raw_key,
+ b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}',
+)
+
+sealed_key = raw_key.to_paserk(sealing_key=public_key_pem)
+unsealed_key = Key.from_paserk(sealed_key, unsealing_key=private_key_pem)
+decoded = pyseto.decode(unsealed_key, token)
+
+assert (
+ decoded.payload
+ == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+)
+```
+
+Key searing for `v1` and `v3` have not been supported yet.
+
+
+## API Reference
+
+See [Documentation](https://pyseto.readthedocs.io/en/stable/api.html).
+
+## Tests
+
+You can run tests from the project root after cloning with:
+
+```sh
+$ tox
+```
+
+## Contributing
+
+We welcome all kind of contributions, filing issues, suggesting new features or sending PRs.
+
+
+%package -n python3-pyseto
+Summary: A Python implementation of PASETO/PASERK.
+Provides: python-pyseto
+BuildRequires: python3-devel
+BuildRequires: python3-setuptools
+BuildRequires: python3-pip
+%description -n python3-pyseto
+# PySETO - A Python implementation of PASETO/PASERK
+
+[![PyPI version](https://badge.fury.io/py/pyseto.svg)](https://badge.fury.io/py/pyseto)
+![PyPI - Python Version](https://img.shields.io/pypi/pyversions/pyseto)
+[![Documentation Status](https://readthedocs.org/projects/pyseto/badge/?version=latest)](https://pyseto.readthedocs.io/en/latest/?badge=latest)
+![Github CI](https://github.com/dajiaji/pyseto/actions/workflows/python-package.yml/badge.svg)
+[![codecov](https://codecov.io/gh/dajiaji/pyseto/branch/main/graph/badge.svg?token=QN8GXEYEP3)](https://codecov.io/gh/dajiaji/pyseto)
+
+
+PySETO is a [PASETO (Platform-Agnostic SEcurity TOkens)](https://paseto.io/)/[PASERK (Platform-Agnostic Serialized Keys)](https://github.com/paseto-standard/paserk) implementation written in Python
+which supports all of the versions ([v1](https://github.com/paseto-standard/paseto-spec/blob/master/docs/01-Protocol-Versions/Version1.md),
+[v2](https://github.com/paseto-standard/paseto-spec/blob/master/docs/01-Protocol-Versions/Version2.md),
+[v3](https://github.com/paseto-standard/paseto-spec/blob/master/docs/01-Protocol-Versions/Version3.md) and
+[v4](https://github.com/paseto-standard/paseto-spec/blob/master/docs/01-Protocol-Versions/Version4.md)) and purposes (`public` and `local`)
+and has passed all of [the official tests](https://github.com/paseto-standard/test-vectors).
+
+You can install PySETO with pip:
+
+```sh
+$ pip install pyseto
+```
+
+PySETO can be used in ease as follows (in case of `v4.public`):
+
+```py
+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-----"
+
+
+# Create a PASETO token.
+private_key = Key.new(version=4, purpose="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"}')
+
+# Decode and verify a PASETO token.
+public_key = Key.new(version=4, purpose="public", key=public_key_pem)
+decoded = pyseto.decode(public_key, token)
+
+assert token == b'v4.public.eyJkYXRhIjogInRoaXMgaXMgYSBzaWduZWQgbWVzc2FnZSIsICJleHAiOiAiMjAyMi0wMS0wMVQwMDowMDowMCswMDowMCJ9l1YiKei2FESvHBSGPkn70eFO1hv3tXH0jph1IfZyEfgm3t1DjkYqD5r4aHWZm1eZs_3_bZ9pBQlZGp0DPSdzDg'
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+```
+
+See following contents or [Documentation](https://pyseto.readthedocs.io/en/stable/) for details.
+
+## Index
+
+- [Installation](#installation)
+- [Supported PASETO Versions](#supported-paseto-versions)
+- [Supported PASERK Types](#supported-paserk-types)
+- [PASETO Usage](#paseto-usage)
+ - [Basic usage: v4.public](#basic-usage-v4public)
+ - [Basic usage: v4.local](#basic-usage-v4local)
+ - [Using serializer/deserializer for payload and footer](#using-serializerdeserializer-for-payload-and-footer)
+ - [Using Paseto class for handling registered claims](#using-paseto-class-for-handling-registered-claims)
+- [PASERK Usage](#paserk-usage)
+ - [Serializing/Deserializing PASERK](#serializingdeserializing-paserk)
+ - [Serializing PASERK ID](#serializing-paserk-id)
+ - [Key Wrapping](#key-wrapping)
+ - [Password-based Key Encryption](#password-based-key-encryption)
+ - [Asymmetric Encryption](#asymmetric-encryption)
+- [API Reference](#api-reference)
+- [Tests](#tests)
+- [Contributing](#contributing)
+
+## Installation
+
+You can install PySETO with pip:
+
+```sh
+$ pip install pyseto
+```
+
+## Supported PASETO Versions
+
+PySETO supports all of PASETO versions and purposes below:
+
+
+| | v4 | v3 | v2 | v1 |
+| ---------| ---- | ---- | ---- | ---- |
+| `local` | ✅ | ✅ | ✅ | ✅ |
+| `public` | ✅ | ✅ | ✅ | ✅ |
+
+
+## Supported PASERK Types
+
+PySETO also supports [PASERK (Platform-Agnostic Serialized Keys)](https://github.com/paseto-standard/paserk).
+Currently, following PASERK types are supported:
+
+
+| | v4 | v3 | v2 | v1 |
+| ------------- | ---- | ---- | ---- | ---- |
+| `lid` | ✅ | ✅ | ✅ | ✅ |
+| `sid` | ✅ | ✅ | ✅ | ✅ |
+| `pid` | ✅ | ✅ | ✅ | ✅ |
+| `local` | ✅ | ✅ | ✅ | ✅ |
+| `secret` | ✅ | ✅ | ✅ | ✅ |
+| `public` | ✅ | ✅ | ✅ | ✅ |
+| `seal` | ✅ | | ✅ | |
+| `local-wrap` | ✅ | ✅ | ✅ | ✅ |
+| `secret-wrap` | ✅ | ✅ | ✅ | ✅ |
+| `local-pw` | ✅ | ✅ | ✅ | ✅ |
+| `secret-pw` | ✅ | ✅ | ✅ | ✅ |
+
+
+## PASETO Usage
+
+By using this PySETO, you can easily create, decode and verify PASETO tokens. Here are sample codes that handle version 4 PySETO tokens.
+
+Please refer to [the Documentation](https://pyseto.readthedocs.io/en/stable/) for all usage examples including other versions.
+
+### Basic usage: v4.public
+
+`v4.public` is one of current PASETO versions to be used for asymmetric authentication (public key signatures).
+
+```py
+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, purpose="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"}')
+
+public_key = Key.new(version=4, purpose="public", key=public_key_pem)
+decoded = pyseto.decode(public_key, token)
+
+assert token == b'v4.public.eyJkYXRhIjogInRoaXMgaXMgYSBzaWduZWQgbWVzc2FnZSIsICJleHAiOiAiMjAyMi0wMS0wMVQwMDowMDowMCswMDowMCJ9l1YiKei2FESvHBSGPkn70eFO1hv3tXH0jph1IfZyEfgm3t1DjkYqD5r4aHWZm1eZs_3_bZ9pBQlZGp0DPSdzDg'
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+```
+
+### Basic usage: v4.local
+
+`v4.local` is one of current PASETO versions to be used for symmetric authenticated encryption.
+
+```py
+import pyseto
+from pyseto import Key
+
+key = Key.new(version=4, purpose="local", key=b"our-secret")
+token = pyseto.encode(key, b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}')
+
+decoded = pyseto.decode(key, token)
+
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+```
+
+### Using serializer/deserializer for payload and footer
+
+By using `serializer` and `deserializer`, you can encode/decode a dict-typed payload and footer included in PASETO tokens into an arbitrary format.
+The following example shows that the payload and the footer in a PASETO token are encoded/decoded as JSON formatted data.
+When specifing dict-typed payload, exp parameter can be used to set the expiration time (seconds) of the token.
+
+```py
+import json
+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, purpose="public", key=private_key_pem)
+public_key = Key.new(version=4, purpose="public", key=public_key_pem)
+token = pyseto.encode(
+ private_key,
+ {"data": "this is a signed message"},
+ footer={"kid": public_key.to_paserk_id()},
+ serializer=json,
+ exp=3600,
+)
+
+decoded = pyseto.decode(public_key, token, deserializer=json)
+
+assert decoded.payload["data"] == "this is a signed message"
+assert decoded.payload["exp"] == "2021-11-11T00:00:00+00:00"
+assert decoded.footer["kid"] == "k4.pid.yh4-bJYjOYAG6CWy0zsfPmpKylxS7uAWrxqVmBN2KAiJ"
+```
+
+### Using `Paseto` class for handling registered claims
+
+By using `Paseto` class, you can change the default value of `exp` (the expiration date ot tokens), whether to include an `iat` claim, and other settings.
+
+Note that `pyseto.encode()` and `pyseto.decode()` are aliases to the `encode()` and `decode()` of the global "Paseto" class instance created with the default settings.
+
+```py
+import json
+import pyseto
+from pyseto import Key, Paseto
+
+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, purpose="public", key=private_key_pem)
+paseto = Paseto.new(exp=3600, include_iat=True) # Default values are exp=0(not specified) and including_iat=False
+token = paseto.encode(
+ private_key,
+ {"data": "this is a signed message"},
+ serializer=json,
+)
+
+public_key = Key.new(version=4, purpose="public", key=public_key_pem)
+decoded = pyseto.decode(public_key, token, deserializer=json)
+
+assert decoded.payload["data"] == "this is a signed message"
+assert decoded.payload["iat"] == "2021-11-11T00:00:00+00:00"
+assert decoded.payload["exp"] == "2021-11-11T01:00:00+00:00"
+```
+
+## PASERK Usage
+
+[PASERK (Platform-Agnostic Serialized Keys)](https://github.com/paseto-standard/paserk) is an extension to PASETO that provides key-wrapping and serialization.
+
+### Serializing/Deserializing PASERK
+
+As shown in the examples above, the `pyseto.Key` used for encryption and signature can be generated from PASERK or converted to PASERK as follows:
+
+```py
+import pyseto
+from pyseto import Key
+
+# pyseto.Key can be generated from PASERK.
+symmetric_key = Key.new(version=4, purpose="local", key=b"our-secret")
+private_key = Key.from_paserk("k4.secret.tMv7Q99M4hByfZU-SnEzB_oZu32fhQQUONnhG5QqN3Qeudu7vAR8A_1wYE4AcfCYfhayi3VyJcEfAEFdDiCxog")
+public_key = Key.from_paserk("k4.public.Hrnbu7wEfAP9cGBOAHHwmH4Wsot1ciXBHwBBXQ4gsaI")
+
+token = pyseto.encode(private_key, b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}')
+decoded = pyseto.decode(public_key, token)
+
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+
+# PASERK can be derived from pyseto.Key.
+assert symmetric_key.to_paserk() == "k4.local.b3VyLXNlY3JldA"
+assert private_key.to_paserk() == "k4.secret.tMv7Q99M4hByfZU-SnEzB_oZu32fhQQUONnhG5QqN3Qeudu7vAR8A_1wYE4AcfCYfhayi3VyJcEfAEFdDiCxog"
+assert public_key.to_paserk() == "k4.public.Hrnbu7wEfAP9cGBOAHHwmH4Wsot1ciXBHwBBXQ4gsaI"
+```
+
+### Serializing PASERK ID
+
+`pyseto.Key` can also be converted to PASERK ID as follows:
+
+```py
+import pyseto
+from pyseto import Key
+
+# pyseto.Key can be generated from PASERK.
+symmetric_key = Key.new(version=4, purpose="local", key=b"our-secret")
+private_key = Key.from_paserk("k4.secret.tMv7Q99M4hByfZU-SnEzB_oZu32fhQQUONnhG5QqN3Qeudu7vAR8A_1wYE4AcfCYfhayi3VyJcEfAEFdDiCxog")
+public_key = Key.from_paserk("k4.public.Hrnbu7wEfAP9cGBOAHHwmH4Wsot1ciXBHwBBXQ4gsaI")
+
+# PASERK ID can be derived from pyseto.Key.
+assert symmetric_key.to_paserk_id() == "k4.lid._D6kgTzxgiPGk35gMj9bukgj4En2H94u22wVX9zaoh05"
+assert private_key.to_paserk() == "k4.secret.tMv7Q99M4hByfZU-SnEzB_oZu32fhQQUONnhG5QqN3Qeudu7vAR8A_1wYE4AcfCYfhayi3VyJcEfAEFdDiCxog"
+assert public_key.to_paserk_id() == "k4.pid.yh4-bJYjOYAG6CWy0zsfPmpKylxS7uAWrxqVmBN2KAiJ"
+```
+
+### Key Wrapping
+
+If you call `to_paserk` with `wrapping_key`, you can get a wrapped (encrypted) PASERK with the wrapping key.
+The wrapped PASERK can be decrypted by calling `from_paserk` with `wrapping key`.
+
+In case of `local-wrap.pie`:
+
+```py
+import pyseto
+from pyseto import Key
+
+raw_key = Key.new(version=4, purpose="local", key=b"our-secret")
+wrapping_key = token_bytes(32)
+wpk = raw_key.to_paserk(wrapping_key=wrapping_key)
+token = pyseto.encode(raw_key, b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}')
+
+unwrapped_key = Key.from_paserk(wpk, wrapping_key=wrapping_key)
+decoded = pyseto.decode(unwrapped_key, token)
+
+# assert wpk == "k4.local-wrap.pie.TNKEwC4K1xBcgJ_GiwWAoRlQFE33HJO3oN9DHEZ05pieSCd-W7bgAL64VG9TZ_pBkuNBFHNrfOGHtnfnhYGdbz5-x3CxShhPJxg"
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+```
+
+In case of `secret-wrap.pie`:
+
+```py
+import pyseto
+from pyseto import Key
+
+raw_private_key = Key.from_paserk(
+ "k4.secret.tMv7Q99M4hByfZU-SnEzB_oZu32fhQQUONnhG5QqN3Qeudu7vAR8A_1wYE4AcfCYfhayi3VyJcEfAEFdDiCxog"
+)
+wrapping_key = token_bytes(32)
+wpk = raw_private_key.to_paserk(wrapping_key=wrapping_key)
+unwrapped_private_key = Key.from_paserk(wpk, wrapping_key=wrapping_key)
+token = pyseto.encode(unwrapped_private_key, b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}')
+
+public_key = Key.from_paserk("k4.public.Hrnbu7wEfAP9cGBOAHHwmH4Wsot1ciXBHwBBXQ4gsaI")
+decoded = pyseto.decode(public_key, token)
+
+# assert wpk == "k4.secret-wrap.pie.excv7V4-NaECy5hpji-tkSkMvyjsAgNxA-mGALgdjyvGNyDlTb89bJ35R1e3tILgbMpEW5WXMXzySe2T-sBz-ZAcs1j7rbD3ZWvsBTM6K5N9wWfAxbR4ppCXH_H5__9yY-kBaF2NimyAJyduhOhSmqLm6TTSucpAOakEJOXePW8"
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+```
+
+### Password-based Key Encryption
+
+If you call `to_paserk` with `password`, you can get a wrapped (encrypted) PASERK with the password.
+The wrapped PASERK can be decrypted by calling `from_paserk` with `passwrod`.
+
+In case of `local-pw`:
+
+```py
+import pyseto
+from pyseto import Key
+
+raw_key = Key.new(version=4, purpose="local", key=b"our-secret")
+token = pyseto.encode(raw_key, b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}')
+
+wpk = raw_key.to_paserk(password="our-secret")
+unwrapped_key = Key.from_paserk(wpk, password="our-secret")
+decoded = pyseto.decode(unwrapped_key, token)
+
+# assert wpk == "k4.local-pw.HrCs9Pu-2LB0l7jkHB-x2gAAAAAA8AAAAAAAAgAAAAGttW0IHZjQCHJdg-Vc3tqO_GSLR4vzLl-yrKk2I-l8YHj6jWpC0lQB2Z7uzTtVyV1rd_EZQPzHdw5VOtyucP0FkCU"
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+```
+
+In case of `secret-pw`:
+
+```py
+import pyseto
+from pyseto import Key
+
+raw_private_key = Key.from_paserk(
+ "k4.secret.tMv7Q99M4hByfZU-SnEzB_oZu32fhQQUONnhG5QqN3Qeudu7vAR8A_1wYE4AcfCYfhayi3VyJcEfAEFdDiCxog"
+)
+wpk = raw_private_key.to_paserk(password="our-secret")
+unwrapped_private_key = Key.from_paserk(wpk, password="our-secret")
+token = pyseto.encode(unwrapped_private_key, b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}')
+
+public_key = Key.from_paserk(
+ "k4.public.Hrnbu7wEfAP9cGBOAHHwmH4Wsot1ciXBHwBBXQ4gsaI"
+)
+decoded = pyseto.decode(public_key, token)
+
+# assert wpk == "k4.secret-pw.MEMW4K1MaD5nWigCLyEyFAAAAAAA8AAAAAAAAgAAAAFU-tArtryNVjS2n2hCYiM11V6tOyuIog69Bjb0yNZanrLJ3afGclb3kPzQ6IhK8ob9E4QgRdEALGWCizZ0RCPFF_M95IQDfmdYKC0Er656UgKUK4UKG9JlxP4o81UwoJoZYz_D1zTlltipEa5RiNvUtNU8vLKoGSY"
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+```
+
+### Asymmetric Encryption
+
+At this time, PySETO supports asymmetric encryption (key sealing) for `v2` and `v4`.
+
+```py
+import pyseto
+from pyseto import Key
+
+private_key_pem = b"-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VuBCIEIFAF7jSCZHFgWvC8hUkXr55Az6Pot2g4zOAUxck0/6x8\n-----END PRIVATE KEY-----"
+public_key_pem = b"-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VuAyEAFv8IXsICYj0paznDK/99GyCsFOIGnfY87ayyNSIvSB4=\n-----END PUBLIC KEY-----"
+
+raw_key = Key.new(version=4, purpose="local", key=b"our-secret")
+token = pyseto.encode(
+ raw_key,
+ b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}',
+)
+
+sealed_key = raw_key.to_paserk(sealing_key=public_key_pem)
+unsealed_key = Key.from_paserk(sealed_key, unsealing_key=private_key_pem)
+decoded = pyseto.decode(unsealed_key, token)
+
+assert (
+ decoded.payload
+ == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+)
+```
+
+Key searing for `v1` and `v3` have not been supported yet.
+
+
+## API Reference
+
+See [Documentation](https://pyseto.readthedocs.io/en/stable/api.html).
+
+## Tests
+
+You can run tests from the project root after cloning with:
+
+```sh
+$ tox
+```
+
+## Contributing
+
+We welcome all kind of contributions, filing issues, suggesting new features or sending PRs.
+
+
+%package help
+Summary: Development documents and examples for pyseto
+Provides: python3-pyseto-doc
+%description help
+# PySETO - A Python implementation of PASETO/PASERK
+
+[![PyPI version](https://badge.fury.io/py/pyseto.svg)](https://badge.fury.io/py/pyseto)
+![PyPI - Python Version](https://img.shields.io/pypi/pyversions/pyseto)
+[![Documentation Status](https://readthedocs.org/projects/pyseto/badge/?version=latest)](https://pyseto.readthedocs.io/en/latest/?badge=latest)
+![Github CI](https://github.com/dajiaji/pyseto/actions/workflows/python-package.yml/badge.svg)
+[![codecov](https://codecov.io/gh/dajiaji/pyseto/branch/main/graph/badge.svg?token=QN8GXEYEP3)](https://codecov.io/gh/dajiaji/pyseto)
+
+
+PySETO is a [PASETO (Platform-Agnostic SEcurity TOkens)](https://paseto.io/)/[PASERK (Platform-Agnostic Serialized Keys)](https://github.com/paseto-standard/paserk) implementation written in Python
+which supports all of the versions ([v1](https://github.com/paseto-standard/paseto-spec/blob/master/docs/01-Protocol-Versions/Version1.md),
+[v2](https://github.com/paseto-standard/paseto-spec/blob/master/docs/01-Protocol-Versions/Version2.md),
+[v3](https://github.com/paseto-standard/paseto-spec/blob/master/docs/01-Protocol-Versions/Version3.md) and
+[v4](https://github.com/paseto-standard/paseto-spec/blob/master/docs/01-Protocol-Versions/Version4.md)) and purposes (`public` and `local`)
+and has passed all of [the official tests](https://github.com/paseto-standard/test-vectors).
+
+You can install PySETO with pip:
+
+```sh
+$ pip install pyseto
+```
+
+PySETO can be used in ease as follows (in case of `v4.public`):
+
+```py
+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-----"
+
+
+# Create a PASETO token.
+private_key = Key.new(version=4, purpose="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"}')
+
+# Decode and verify a PASETO token.
+public_key = Key.new(version=4, purpose="public", key=public_key_pem)
+decoded = pyseto.decode(public_key, token)
+
+assert token == b'v4.public.eyJkYXRhIjogInRoaXMgaXMgYSBzaWduZWQgbWVzc2FnZSIsICJleHAiOiAiMjAyMi0wMS0wMVQwMDowMDowMCswMDowMCJ9l1YiKei2FESvHBSGPkn70eFO1hv3tXH0jph1IfZyEfgm3t1DjkYqD5r4aHWZm1eZs_3_bZ9pBQlZGp0DPSdzDg'
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+```
+
+See following contents or [Documentation](https://pyseto.readthedocs.io/en/stable/) for details.
+
+## Index
+
+- [Installation](#installation)
+- [Supported PASETO Versions](#supported-paseto-versions)
+- [Supported PASERK Types](#supported-paserk-types)
+- [PASETO Usage](#paseto-usage)
+ - [Basic usage: v4.public](#basic-usage-v4public)
+ - [Basic usage: v4.local](#basic-usage-v4local)
+ - [Using serializer/deserializer for payload and footer](#using-serializerdeserializer-for-payload-and-footer)
+ - [Using Paseto class for handling registered claims](#using-paseto-class-for-handling-registered-claims)
+- [PASERK Usage](#paserk-usage)
+ - [Serializing/Deserializing PASERK](#serializingdeserializing-paserk)
+ - [Serializing PASERK ID](#serializing-paserk-id)
+ - [Key Wrapping](#key-wrapping)
+ - [Password-based Key Encryption](#password-based-key-encryption)
+ - [Asymmetric Encryption](#asymmetric-encryption)
+- [API Reference](#api-reference)
+- [Tests](#tests)
+- [Contributing](#contributing)
+
+## Installation
+
+You can install PySETO with pip:
+
+```sh
+$ pip install pyseto
+```
+
+## Supported PASETO Versions
+
+PySETO supports all of PASETO versions and purposes below:
+
+
+| | v4 | v3 | v2 | v1 |
+| ---------| ---- | ---- | ---- | ---- |
+| `local` | ✅ | ✅ | ✅ | ✅ |
+| `public` | ✅ | ✅ | ✅ | ✅ |
+
+
+## Supported PASERK Types
+
+PySETO also supports [PASERK (Platform-Agnostic Serialized Keys)](https://github.com/paseto-standard/paserk).
+Currently, following PASERK types are supported:
+
+
+| | v4 | v3 | v2 | v1 |
+| ------------- | ---- | ---- | ---- | ---- |
+| `lid` | ✅ | ✅ | ✅ | ✅ |
+| `sid` | ✅ | ✅ | ✅ | ✅ |
+| `pid` | ✅ | ✅ | ✅ | ✅ |
+| `local` | ✅ | ✅ | ✅ | ✅ |
+| `secret` | ✅ | ✅ | ✅ | ✅ |
+| `public` | ✅ | ✅ | ✅ | ✅ |
+| `seal` | ✅ | | ✅ | |
+| `local-wrap` | ✅ | ✅ | ✅ | ✅ |
+| `secret-wrap` | ✅ | ✅ | ✅ | ✅ |
+| `local-pw` | ✅ | ✅ | ✅ | ✅ |
+| `secret-pw` | ✅ | ✅ | ✅ | ✅ |
+
+
+## PASETO Usage
+
+By using this PySETO, you can easily create, decode and verify PASETO tokens. Here are sample codes that handle version 4 PySETO tokens.
+
+Please refer to [the Documentation](https://pyseto.readthedocs.io/en/stable/) for all usage examples including other versions.
+
+### Basic usage: v4.public
+
+`v4.public` is one of current PASETO versions to be used for asymmetric authentication (public key signatures).
+
+```py
+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, purpose="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"}')
+
+public_key = Key.new(version=4, purpose="public", key=public_key_pem)
+decoded = pyseto.decode(public_key, token)
+
+assert token == b'v4.public.eyJkYXRhIjogInRoaXMgaXMgYSBzaWduZWQgbWVzc2FnZSIsICJleHAiOiAiMjAyMi0wMS0wMVQwMDowMDowMCswMDowMCJ9l1YiKei2FESvHBSGPkn70eFO1hv3tXH0jph1IfZyEfgm3t1DjkYqD5r4aHWZm1eZs_3_bZ9pBQlZGp0DPSdzDg'
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+```
+
+### Basic usage: v4.local
+
+`v4.local` is one of current PASETO versions to be used for symmetric authenticated encryption.
+
+```py
+import pyseto
+from pyseto import Key
+
+key = Key.new(version=4, purpose="local", key=b"our-secret")
+token = pyseto.encode(key, b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}')
+
+decoded = pyseto.decode(key, token)
+
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+```
+
+### Using serializer/deserializer for payload and footer
+
+By using `serializer` and `deserializer`, you can encode/decode a dict-typed payload and footer included in PASETO tokens into an arbitrary format.
+The following example shows that the payload and the footer in a PASETO token are encoded/decoded as JSON formatted data.
+When specifing dict-typed payload, exp parameter can be used to set the expiration time (seconds) of the token.
+
+```py
+import json
+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, purpose="public", key=private_key_pem)
+public_key = Key.new(version=4, purpose="public", key=public_key_pem)
+token = pyseto.encode(
+ private_key,
+ {"data": "this is a signed message"},
+ footer={"kid": public_key.to_paserk_id()},
+ serializer=json,
+ exp=3600,
+)
+
+decoded = pyseto.decode(public_key, token, deserializer=json)
+
+assert decoded.payload["data"] == "this is a signed message"
+assert decoded.payload["exp"] == "2021-11-11T00:00:00+00:00"
+assert decoded.footer["kid"] == "k4.pid.yh4-bJYjOYAG6CWy0zsfPmpKylxS7uAWrxqVmBN2KAiJ"
+```
+
+### Using `Paseto` class for handling registered claims
+
+By using `Paseto` class, you can change the default value of `exp` (the expiration date ot tokens), whether to include an `iat` claim, and other settings.
+
+Note that `pyseto.encode()` and `pyseto.decode()` are aliases to the `encode()` and `decode()` of the global "Paseto" class instance created with the default settings.
+
+```py
+import json
+import pyseto
+from pyseto import Key, Paseto
+
+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, purpose="public", key=private_key_pem)
+paseto = Paseto.new(exp=3600, include_iat=True) # Default values are exp=0(not specified) and including_iat=False
+token = paseto.encode(
+ private_key,
+ {"data": "this is a signed message"},
+ serializer=json,
+)
+
+public_key = Key.new(version=4, purpose="public", key=public_key_pem)
+decoded = pyseto.decode(public_key, token, deserializer=json)
+
+assert decoded.payload["data"] == "this is a signed message"
+assert decoded.payload["iat"] == "2021-11-11T00:00:00+00:00"
+assert decoded.payload["exp"] == "2021-11-11T01:00:00+00:00"
+```
+
+## PASERK Usage
+
+[PASERK (Platform-Agnostic Serialized Keys)](https://github.com/paseto-standard/paserk) is an extension to PASETO that provides key-wrapping and serialization.
+
+### Serializing/Deserializing PASERK
+
+As shown in the examples above, the `pyseto.Key` used for encryption and signature can be generated from PASERK or converted to PASERK as follows:
+
+```py
+import pyseto
+from pyseto import Key
+
+# pyseto.Key can be generated from PASERK.
+symmetric_key = Key.new(version=4, purpose="local", key=b"our-secret")
+private_key = Key.from_paserk("k4.secret.tMv7Q99M4hByfZU-SnEzB_oZu32fhQQUONnhG5QqN3Qeudu7vAR8A_1wYE4AcfCYfhayi3VyJcEfAEFdDiCxog")
+public_key = Key.from_paserk("k4.public.Hrnbu7wEfAP9cGBOAHHwmH4Wsot1ciXBHwBBXQ4gsaI")
+
+token = pyseto.encode(private_key, b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}')
+decoded = pyseto.decode(public_key, token)
+
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+
+# PASERK can be derived from pyseto.Key.
+assert symmetric_key.to_paserk() == "k4.local.b3VyLXNlY3JldA"
+assert private_key.to_paserk() == "k4.secret.tMv7Q99M4hByfZU-SnEzB_oZu32fhQQUONnhG5QqN3Qeudu7vAR8A_1wYE4AcfCYfhayi3VyJcEfAEFdDiCxog"
+assert public_key.to_paserk() == "k4.public.Hrnbu7wEfAP9cGBOAHHwmH4Wsot1ciXBHwBBXQ4gsaI"
+```
+
+### Serializing PASERK ID
+
+`pyseto.Key` can also be converted to PASERK ID as follows:
+
+```py
+import pyseto
+from pyseto import Key
+
+# pyseto.Key can be generated from PASERK.
+symmetric_key = Key.new(version=4, purpose="local", key=b"our-secret")
+private_key = Key.from_paserk("k4.secret.tMv7Q99M4hByfZU-SnEzB_oZu32fhQQUONnhG5QqN3Qeudu7vAR8A_1wYE4AcfCYfhayi3VyJcEfAEFdDiCxog")
+public_key = Key.from_paserk("k4.public.Hrnbu7wEfAP9cGBOAHHwmH4Wsot1ciXBHwBBXQ4gsaI")
+
+# PASERK ID can be derived from pyseto.Key.
+assert symmetric_key.to_paserk_id() == "k4.lid._D6kgTzxgiPGk35gMj9bukgj4En2H94u22wVX9zaoh05"
+assert private_key.to_paserk() == "k4.secret.tMv7Q99M4hByfZU-SnEzB_oZu32fhQQUONnhG5QqN3Qeudu7vAR8A_1wYE4AcfCYfhayi3VyJcEfAEFdDiCxog"
+assert public_key.to_paserk_id() == "k4.pid.yh4-bJYjOYAG6CWy0zsfPmpKylxS7uAWrxqVmBN2KAiJ"
+```
+
+### Key Wrapping
+
+If you call `to_paserk` with `wrapping_key`, you can get a wrapped (encrypted) PASERK with the wrapping key.
+The wrapped PASERK can be decrypted by calling `from_paserk` with `wrapping key`.
+
+In case of `local-wrap.pie`:
+
+```py
+import pyseto
+from pyseto import Key
+
+raw_key = Key.new(version=4, purpose="local", key=b"our-secret")
+wrapping_key = token_bytes(32)
+wpk = raw_key.to_paserk(wrapping_key=wrapping_key)
+token = pyseto.encode(raw_key, b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}')
+
+unwrapped_key = Key.from_paserk(wpk, wrapping_key=wrapping_key)
+decoded = pyseto.decode(unwrapped_key, token)
+
+# assert wpk == "k4.local-wrap.pie.TNKEwC4K1xBcgJ_GiwWAoRlQFE33HJO3oN9DHEZ05pieSCd-W7bgAL64VG9TZ_pBkuNBFHNrfOGHtnfnhYGdbz5-x3CxShhPJxg"
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+```
+
+In case of `secret-wrap.pie`:
+
+```py
+import pyseto
+from pyseto import Key
+
+raw_private_key = Key.from_paserk(
+ "k4.secret.tMv7Q99M4hByfZU-SnEzB_oZu32fhQQUONnhG5QqN3Qeudu7vAR8A_1wYE4AcfCYfhayi3VyJcEfAEFdDiCxog"
+)
+wrapping_key = token_bytes(32)
+wpk = raw_private_key.to_paserk(wrapping_key=wrapping_key)
+unwrapped_private_key = Key.from_paserk(wpk, wrapping_key=wrapping_key)
+token = pyseto.encode(unwrapped_private_key, b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}')
+
+public_key = Key.from_paserk("k4.public.Hrnbu7wEfAP9cGBOAHHwmH4Wsot1ciXBHwBBXQ4gsaI")
+decoded = pyseto.decode(public_key, token)
+
+# assert wpk == "k4.secret-wrap.pie.excv7V4-NaECy5hpji-tkSkMvyjsAgNxA-mGALgdjyvGNyDlTb89bJ35R1e3tILgbMpEW5WXMXzySe2T-sBz-ZAcs1j7rbD3ZWvsBTM6K5N9wWfAxbR4ppCXH_H5__9yY-kBaF2NimyAJyduhOhSmqLm6TTSucpAOakEJOXePW8"
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+```
+
+### Password-based Key Encryption
+
+If you call `to_paserk` with `password`, you can get a wrapped (encrypted) PASERK with the password.
+The wrapped PASERK can be decrypted by calling `from_paserk` with `passwrod`.
+
+In case of `local-pw`:
+
+```py
+import pyseto
+from pyseto import Key
+
+raw_key = Key.new(version=4, purpose="local", key=b"our-secret")
+token = pyseto.encode(raw_key, b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}')
+
+wpk = raw_key.to_paserk(password="our-secret")
+unwrapped_key = Key.from_paserk(wpk, password="our-secret")
+decoded = pyseto.decode(unwrapped_key, token)
+
+# assert wpk == "k4.local-pw.HrCs9Pu-2LB0l7jkHB-x2gAAAAAA8AAAAAAAAgAAAAGttW0IHZjQCHJdg-Vc3tqO_GSLR4vzLl-yrKk2I-l8YHj6jWpC0lQB2Z7uzTtVyV1rd_EZQPzHdw5VOtyucP0FkCU"
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+```
+
+In case of `secret-pw`:
+
+```py
+import pyseto
+from pyseto import Key
+
+raw_private_key = Key.from_paserk(
+ "k4.secret.tMv7Q99M4hByfZU-SnEzB_oZu32fhQQUONnhG5QqN3Qeudu7vAR8A_1wYE4AcfCYfhayi3VyJcEfAEFdDiCxog"
+)
+wpk = raw_private_key.to_paserk(password="our-secret")
+unwrapped_private_key = Key.from_paserk(wpk, password="our-secret")
+token = pyseto.encode(unwrapped_private_key, b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}')
+
+public_key = Key.from_paserk(
+ "k4.public.Hrnbu7wEfAP9cGBOAHHwmH4Wsot1ciXBHwBBXQ4gsaI"
+)
+decoded = pyseto.decode(public_key, token)
+
+# assert wpk == "k4.secret-pw.MEMW4K1MaD5nWigCLyEyFAAAAAAA8AAAAAAAAgAAAAFU-tArtryNVjS2n2hCYiM11V6tOyuIog69Bjb0yNZanrLJ3afGclb3kPzQ6IhK8ob9E4QgRdEALGWCizZ0RCPFF_M95IQDfmdYKC0Er656UgKUK4UKG9JlxP4o81UwoJoZYz_D1zTlltipEa5RiNvUtNU8vLKoGSY"
+assert decoded.payload == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+```
+
+### Asymmetric Encryption
+
+At this time, PySETO supports asymmetric encryption (key sealing) for `v2` and `v4`.
+
+```py
+import pyseto
+from pyseto import Key
+
+private_key_pem = b"-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VuBCIEIFAF7jSCZHFgWvC8hUkXr55Az6Pot2g4zOAUxck0/6x8\n-----END PRIVATE KEY-----"
+public_key_pem = b"-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VuAyEAFv8IXsICYj0paznDK/99GyCsFOIGnfY87ayyNSIvSB4=\n-----END PUBLIC KEY-----"
+
+raw_key = Key.new(version=4, purpose="local", key=b"our-secret")
+token = pyseto.encode(
+ raw_key,
+ b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}',
+)
+
+sealed_key = raw_key.to_paserk(sealing_key=public_key_pem)
+unsealed_key = Key.from_paserk(sealed_key, unsealing_key=private_key_pem)
+decoded = pyseto.decode(unsealed_key, token)
+
+assert (
+ decoded.payload
+ == b'{"data": "this is a signed message", "exp": "2022-01-01T00:00:00+00:00"}'
+)
+```
+
+Key searing for `v1` and `v3` have not been supported yet.
+
+
+## API Reference
+
+See [Documentation](https://pyseto.readthedocs.io/en/stable/api.html).
+
+## Tests
+
+You can run tests from the project root after cloning with:
+
+```sh
+$ tox
+```
+
+## Contributing
+
+We welcome all kind of contributions, filing issues, suggesting new features or sending PRs.
+
+
+%prep
+%autosetup -n pyseto-1.7.2
+
+%build
+%py3_build
+
+%install
+%py3_install
+install -d -m755 %{buildroot}/%{_pkgdocdir}
+if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi
+if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi
+if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi
+if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi
+pushd %{buildroot}
+if [ -d usr/lib ]; then
+ find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/lib64 ]; then
+ find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/bin ]; then
+ find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/sbin ]; then
+ find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+touch doclist.lst
+if [ -d usr/share/man ]; then
+ find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst
+fi
+popd
+mv %{buildroot}/filelist.lst .
+mv %{buildroot}/doclist.lst .
+
+%files -n python3-pyseto -f filelist.lst
+%dir %{python3_sitelib}/*
+
+%files help -f doclist.lst
+%{_docdir}/*
+
+%changelog
+* Wed May 17 2023 Python_Bot <Python_Bot@openeuler.org> - 1.7.2-1
+- Package Spec generated