# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['cwt', 'cwt.algs', 'cwt.helpers', 'cwt.recipient_algs']

package_data = \
{'': ['*']}

install_requires = \
['asn1crypto>=1.4.0,<2.0.0',
 'cbor2>=5.4.2,<6.0.0',
 'certvalidator>=0.11.1,<0.12.0',
 'cryptography>=36.0.0,<37.0.0']

extras_require = \
{':extra == "docs"': ['Sphinx[docs]>=4.3.1,<5.0.0',
                      'sphinx-autodoc-typehints[docs]>=1.12.0,<2.0.0',
                      'sphinx-rtd-theme[docs]>=1.0.0,<2.0.0']}

setup_kwargs = {
    'name': 'cwt',
    'version': '1.5.1',
    'description': 'A Python implementation of CWT/COSE.',
    'long_description': '# Python CWT - A Python implementation of CWT/COSE\n\n[![PyPI version](https://badge.fury.io/py/cwt.svg)](https://badge.fury.io/py/cwt)\n![PyPI - Python Version](https://img.shields.io/pypi/pyversions/cwt)\n[![Documentation Status](https://readthedocs.org/projects/python-cwt/badge/?version=latest)](https://python-cwt.readthedocs.io/en/latest/?badge=latest)\n![Github CI](https://github.com/dajiaji/python-cwt/actions/workflows/python-package.yml/badge.svg)\n[![codecov](https://codecov.io/gh/dajiaji/python-cwt/branch/main/graph/badge.svg?token=QN8GXEYEP3)](https://codecov.io/gh/dajiaji/python-cwt)\n\n\nPython CWT is a CBOR Web Token (CWT) and CBOR Object Signing and Encryption (COSE)\nimplementation compliant with:\n- [RFC8392: CWT (CBOR Web Token)](https://tools.ietf.org/html/rfc8392)\n- [RFC8152: COSE (CBOR Object Signing and Encryption)](https://tools.ietf.org/html/rfc8152)\n- and related various specifications. See [Referenced Specifications](#referenced-specifications).\n\nIt is designed to make users who already know about [JWS](https://tools.ietf.org/html/rfc7515)/[JWE](https://tools.ietf.org/html/rfc7516)/[JWT](https://tools.ietf.org/html/rfc7519)\nbe able to use it in ease. Little knowledge of [CBOR](https://tools.ietf.org/html/rfc7049)/[COSE](https://tools.ietf.org/html/rfc8152)/[CWT](https://tools.ietf.org/html/rfc8392)\nis required to use it.\n\nYou can install Python CWT with pip:\n\n\n```sh\n$ pip install cwt\n```\n\nAnd then, you can use it as follows:\n\n```py\n>>> import cwt\n>>> from cwt import COSEKey\n>>> key = COSEKey.from_symmetric_key(alg="HS256", kid="01")\n>>> token = cwt.encode({"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, key)\n>>> token.hex()\n\'d18443a10105a05835a60172636f6170733a2f2f61732e657861\'...\n>>> cwt.decode(token, key)\n{1: \'coaps://as.example\', 2: \'dajiaji\', 7: b\'123\', 4: 1620088759, 5: 1620085159, 6: 1620085159}\n```\n\nSee [Documentation](https://python-cwt.readthedocs.io/en/stable/) for details.\n\n## Index\n\n- [Installation](#installation)\n- [CWT Usage Examples](#cwt-usage-examples)\n    - [MACed CWT](#maced-cwt)\n    - [Signed CWT](#signed-cwt)\n    - [Encrypted CWT](#encrypted-cwt)\n    - [Nested CWT](#nested-cwt)\n    - [CWT with User Settings (e.g., expires\\_in)](#cwt-with-user-settings)\n    - [CWT with User-Defined Claims](#cwt-with-user-defined-claims)\n    - [CWT with PoP Key](#cwt-with-pop-key)\n    - [CWT with Private CA](#cwt-with-private-ca)\n    - [CWT for EUDCC (EU Digital COVID Certificate)](#cwt-for-eudcc-eu-digital-covid-certificate)\n- [COSE Usage Examples](#cose-usage-examples)\n    - [COSE MAC0](#cose-mac0)\n    - [COSE MAC](#cose-mac)\n        - [Direct Key Distribution](#direct-key-distribution-for-mac)\n        - [Direct Key with KDF](#direct-key-with-kdf-for-mac)\n        - [AES Key Wrap](#aes-key-wrap-for-mac)\n        - [Direct key Agreement](#direct-key-agreement-for-mac)\n        - [Key Agreement with Key Wrap](#key-agreement-with-key-wrap-for-mac)\n    - [COSE Encrypt0](#cose-encrypt0)\n    - [COSE Encrypt](#cose-encrypt)\n        - [Direct Key Distribution](#direct-key-distribution-for-encryption)\n        - [Direct Key with KDF](#direct-key-with-kdf-for-encryption)\n        - [AES Key Wrap](#aes-key-wrap-for-encryption)\n        - [Direct key Agreement](#direct-key-agreement-for-encryption)\n        - [Key Agreement with Key Wrap](#key-agreement-with-key-wrap-for-encryption)\n    - [COSE Signature1](#cose-signature1)\n    - [COSE Signature](#cose-signature)\n- [API Reference](#api-reference)\n- [Supported CWT Claims](#supported-cwt-claims)\n- [Supported COSE Algorithms](#supported-cose-algorithms)\n- [Referenced Specifications](#referenced-specifications)\n- [Tests](#tests)\n- [Contributing](#contributing)\n\n## Installation\n\nInstall with pip:\n\n```\npip install cwt\n```\n\n## CWT Usage Examples\n\nFollowings are typical and basic examples which create various types of CWTs, verify and decode them.\n\n[CWT API](https://python-cwt.readthedocs.io/en/stable/api.html) in the examples are built\non top of [COSE API](https://python-cwt.readthedocs.io/en/stable/api.html#cwt.COSE).\n\nSee [API Reference](https://python-cwt.readthedocs.io/en/stable/api.html) and\n[CWT Usage Examples on document](https://python-cwt.readthedocs.io/en/stable/cwt_usage.html)\nfor more details.\n\n### MACed CWT\n\nCreate a MACed CWT with `HS256`, verify and decode it as follows:\n\n```py\nimport cwt\nfrom cwt import Claims, COSEKey\n\ntry:\n    key = COSEKey.from_symmetric_key(alg="HS256", kid="01")\n    token = cwt.encode({"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, key)\n    decoded = cwt.decode(token, key)\n\n    # If you want to treat the result like a JWT;\n    readable = Claims.new(decoded)\n    assert readable.iss == \'coaps://as.example\'\n    assert readable.sub == \'dajiaji\'\n    assert readable.cti == \'123\'\n    # readable.exp == 1620088759\n    # readable.nbf == 1620085159\n    # readable.iat == 1620085159\n\nexcept Exception as err:\n    # All the other examples in this document omit error handling but this CWT library\n    # can throw following errors:\n    #   ValueError: Invalid arguments.\n    #   EncodeError: Failed to encode.\n    #   VerifyError: Failed to verify.\n    #   DecodeError: Failed to decode.\n    print(err)\n```\n\nA raw CWT structure (Dict[int, Any]) can also be used as follows:\n\n```py\nimport cwt\nfrom cwt import COSEKey\n\nkey = COSEKey.from_symmetric_key(alg="HS256", kid="01")\ntoken = cwt.encode({1: "coaps://as.example", 2: "dajiaji", 7: b"123"}, key)\ndecoded = cwt.decode(token, key)\n```\n\nMAC algorithms other than `HS256` are listed in\n[Supported COSE Algorithms](https://python-cwt.readthedocs.io/en/stable/algorithms.html).\n\n### Signed CWT\n\nCreate an `Ed25519` key pair:\n\n```sh\n$ openssl genpkey -algorithm ed25519 -out private_key.pem\n$ openssl pkey -in private_key.pem -pubout -out public_key.pem\n```\n\nCreate a Signed CWT with `Ed25519`, verify and decode it with the key pair as follows:\n\n```py\nimport cwt\nfrom cwt import COSEKey\n\n# The sender side:\nwith open("./private_key.pem") as key_file:\n    private_key = COSEKey.from_pem(key_file.read(), kid="01")\ntoken = cwt.encode(\n    {"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, private_key\n)\n\n# The recipient side:\nwith open("./public_key.pem") as key_file:\n    public_key = COSEKey.from_pem(key_file.read(), kid="01")\ndecoded = cwt.decode(token, public_key)\n```\n\nJWKs can also be used instead of the PEM-formatted keys as follows:\n\n```py\nimport cwt\nfrom cwt import COSEKey\n\n# The sender side:\nprivate_key = COSEKey.from_jwk({\n    "kid": "01",\n    "kty": "OKP",\n    "key_ops": ["sign"],\n    "alg": "EdDSA",\n    "crv": "Ed25519",\n    "x": "2E6dX83gqD_D0eAmqnaHe1TC1xuld6iAKXfw2OVATr0",\n    "d": "L8JS08VsFZoZxGa9JvzYmCWOwg7zaKcei3KZmYsj7dc",\n})\ntoken = cwt.encode(\n    {"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, private_key\n)\n\n# The recipient side:\npublic_key = COSEKey.from_jwk({\n    "kid": "01",\n    "kty": "OKP",\n    "key_ops": ["verify"],\n    "crv": "Ed25519",\n    "x": "2E6dX83gqD_D0eAmqnaHe1TC1xuld6iAKXfw2OVATr0",\n})\ndecoded = cwt.decode(token, public_key)\n```\n\nSigning algorithms other than `Ed25519` are listed in\n[Supported COSE Algorithms](https://python-cwt.readthedocs.io/en/stable/algorithms.html).\n\n### Encrypted CWT\n\nCreate an encrypted CWT with `ChaCha20/Poly1305` and decrypt it as follows:\n\n```py\nimport cwt\nfrom cwt import COSEKey\n\nenc_key = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305", kid="01")\ntoken = cwt.encode({"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, enc_key)\ndecoded = cwt.decode(token, enc_key)\n```\n\nEncryption algorithms other than `ChaCha20/Poly1305` are listed in\n[Supported COSE Algorithms](https://python-cwt.readthedocs.io/en/stable/algorithms.html).\n\n### Nested CWT\n\nCreate a signed CWT and encrypt it, and then decrypt and verify the nested CWT as follows.\n\n```py\nimport cwt\nfrom cwt import COSEKey\n\n# A shared encryption key.\nenc_key = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305", kid="enc-01")\n\n# Creates a CWT with ES256 signing.\nwith open("./private_key.pem") as key_file:\n    private_key = COSEKey.from_pem(key_file.read(), kid="sig-01")\ntoken = cwt.encode(\n    {"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, private_key\n)\n\n# Encrypts the signed CWT.\nnested = cwt.encode(token, enc_key)\n\n# Decrypts and verifies the nested CWT.\nwith open("./public_key.pem") as key_file:\n    public_key = COSEKey.from_pem(key_file.read(), kid="sig-01")\ndecoded = cwt.decode(nested, [enc_key, public_key])\n```\n\n### CWT with User Settings\n\nThe `cwt` in `cwt.encode()` and `cwt.decode()` above is a global `CWT` class instance created\nwith default settings in advance. The default settings are as follows:\n- `expires_in`: `3600` seconds. This is the default lifetime in seconds of CWTs.\n- `leeway`: `60` seconds. This is the default leeway in seconds for validating `exp` and `nbf`.\n\nIf you want to change the settings, you can create your own `CWT` class instance as follows:\n\n```py\nfrom cwt import COSEKey, CWT\n\nkey = COSEKey.from_symmetric_key(alg="HS256", kid="01")\nmycwt = CWT.new(expires_in=3600*24, leeway=10)\ntoken = mycwt.encode({"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, key)\ndecoded = mycwt.decode(token, key)\n```\n\n### CWT with User-Defined Claims\n\nYou can use your own claims as follows:\n\nNote that such user-defined claim\'s key should be less than -65536.\n\n```py\nimport cwt\nfrom cwt import COSEKey\n\n# The sender side:\nwith open("./private_key.pem") as key_file:\n    private_key = COSEKey.from_pem(key_file.read(), kid="01")\ntoken = cwt.encode(\n    {\n        1: "coaps://as.example",  # iss\n        2: "dajiaji",  # sub\n        7: b"123",  # cti\n        -70001: "foo",\n        -70002: ["bar"],\n        -70003: {"baz": "qux"},\n        -70004: 123,\n    },\n    private_key,\n)\n\n# The recipient side:\nwith open("./public_key.pem") as key_file:\n    public_key = COSEKey.from_pem(key_file.read(), kid="01")\nraw = cwt.decode(token, public_key)\nassert raw[-70001] == "foo"\nassert raw[-70002][0] == "bar"\nassert raw[-70003]["baz"] == "qux"\nassert raw[-70004] == 123\n\nreadable = Claims.new(raw)\nassert readable.get(-70001) == "foo"\nassert readable.get(-70002)[0] == "bar"\nassert readable.get(-70003)["baz"] == "qux"\nassert readable.get(-70004) == 123\n```\n\nUser-defined claims can also be used with JSON-based claims as follows:\n\n```py\nimport cwt\nfrom cwt import Claims, COSEKey\n\nwith open("./private_key.pem") as key_file:\n    private_key = COSEKey.from_pem(key_file.read(), kid="01")\n\nmy_claim_names = {\n    "ext_1": -70001,\n    "ext_2": -70002,\n    "ext_3": -70003,\n    "ext_4": -70004,\n}\n\ncwt.set_private_claim_names(my_claim_names)\ntoken = cwt.encode(\n    {\n        "iss": "coaps://as.example",\n        "sub": "dajiaji",\n        "cti": b"123",\n        "ext_1": "foo",\n        "ext_2": ["bar"],\n        "ext_3": {"baz": "qux"},\n        "ext_4": 123,\n    },\n    private_key,\n)\n\nwith open("./public_key.pem") as key_file:\n    public_key = COSEKey.from_pem(key_file.read(), kid="01")\n\nraw = cwt.decode(token, public_key)\nreadable = Claims.new(\n    raw,\n    private_claims_names=my_claim_names,\n)\nassert readable.get("ext_1") == "foo"\nassert readable.get("ext_2")[0] == "bar"\nassert readable.get("ext_3")["baz"] == "qux"\nassert readable.get("ext_4") == 123\n```\n\n\n### CWT with PoP Key\n\nPython CWT supports [Proof-of-Possession Key Semantics for CBOR Web Tokens (CWTs)](https://tools.ietf.org/html/rfc8747).\nA CWT can include a PoP key as follows:\n\nOn the issuer side:\n\n```py\nimport cwt\nfrom cwt import COSEKey\n\n# Prepares a signing key for CWT in advance.\nwith open("./private_key_of_issuer.pem") as key_file:\n    private_key = COSEKey.from_pem(key_file.read(), kid="issuer-01")\n\n# Sets the PoP key to a CWT for the presenter.\ntoken = cwt.encode(\n    {\n        "iss": "coaps://as.example",\n        "sub": "dajiaji",\n        "cti": "123",\n        "cnf": {\n            "jwk": {  # Provided by the CWT presenter.\n                "kty": "OKP",\n                "use": "sig",\n                "crv": "Ed25519",\n                "kid": "presenter-01",\n                "x": "2E6dX83gqD_D0eAmqnaHe1TC1xuld6iAKXfw2OVATr0",\n                "alg": "EdDSA",\n            },\n        },\n    },\n    private_key,\n)\n\n# Issues the token to the presenter.\n```\n\nOn the CWT presenter side:\n\n```py\nimport cwt\nfrom cwt import COSEKey\n\n# Prepares a private PoP key in advance.\nwith open("./private_pop_key.pem") as key_file:\n    pop_key_private = COSEKey.from_pem(key_file.read(), kid="presenter-01")\n\n# Receives a message (e.g., nonce)  from the recipient.\nmsg = b"could-you-sign-this-message?"  # Provided by recipient.\n\n# Signs the message with the private PoP key.\nsig = pop_key_private.sign(msg)\n\n# Sends the msg and the sig with the CWT to the recipient.\n```\n\nOn the CWT recipient side:\n\n```py\nimport cwt\nfrom cwt import Claims, COSEKey\n\n# Prepares the public key of the issuer in advance.\nwith open("./public_key_of_issuer.pem") as key_file:\n    public_key = COSEKey.from_pem(key_file.read(), kid="issuer-01")\n\n# Verifies and decodes the CWT received from the presenter.\nraw = cwt.decode(token, public_key)\ndecoded = Claims.new(raw)\n\n# Extracts the PoP key from the CWT.\nextracted_pop_key = COSEKey.new(decoded.cnf)  # = raw[8][1]\n\n# Then, verifies the message sent by the presenter\n# with the signature which is also sent by the presenter as follows:\nextracted_pop_key.verify(msg, sig)\n```\n\n[Usage Examples](https://python-cwt.readthedocs.io/en/stable/cwt_usage.html#cwt-with-pop-key)\nshows other examples which use other confirmation methods for PoP keys.\n\n### CWT with Private CA\n\nPython CWT supports the case of using an arbitrary private CA as a root of trust.\nIn this case, a COSE message sender needs to specify the trust relationship chaining up to the root CA by using `x5chain` header parameter.\nOn the other hand, a COSE message receiver needs to specify trusted root CAs by using `ca_certs` parameter of CWT/COSE constructor (`CWT.new()` or `COSE.new()`).\n\n```py\nimport cwt\nfrom cwt import Claims, COSEKey\n\n# The sernder side:\nwith open("./private_key_of_cert.pem")) as f:\n    private_key = COSEKey.from_pem(f.read(), kid="01")\n\ntoken = cwt.encode(\n    {"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, private_key\n)\n\n# The recipient side:\npublic_key = COSEKey.from_jwk(\n    {\n        "kty": "EC",\n        "use": "sig",\n        "crv": "P-256",\n        "kid": "P-256-01",\n        "x": "oONCv1QoiajIbcW21Dqy6EnGvBTuF26GU7dy6JzOfXk",\n        "y": "sl6k77K0TS36FW-TyEGLHY14ovZfdZ9DZWsbA8BTHGc",\n        "x5c": [\n          # The DER formatted X509 certificate which pairs with the private_key_of_cert.pem above.\n          "MIIClDCCAXygAwIBAgIBBDANBgkqhkiG9w0BAQsFADBmMQswCQYDVQQGEwJKUDEOMAwGA1UECAwFVG9reW8xEDAOBgNVBAoMB2RhamlhamkxEzARBgNVBAMMCnB5dGhvbi1jd3QxIDAeBgkqhkiG9w0BCQEWEWRhamlhamlAZ21haWwuY29tMB4XDTIxMTAwMzEzMDE1MFoXDTMxMTAwMTEzMDE1MFowZDELMAkGA1UEBhMCSlAxDjAMBgNVBAgMBVRva3lvMQ0wCwYDVQQKDAR0ZXN0MRUwEwYDVQQDDAx0ZXN0LmV4YW1wbGUxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASg40K_VCiJqMhtxbbUOrLoSca8FO4XboZTt3LonM59ebJepO-ytE0t-hVvk8hBix2NeKL2X3WfQ2VrGwPAUxxnoxowGDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIE8DANBgkqhkiG9w0BAQsFAAOCAQEAZFfvFbaDk_DmG2cPGTwqwnFok1QnH2Tzkjk7p4vs1ycWzEDltkhyzcJxTSHoQGdykf7fG8NCrEqfi1G3hOyAtGxVIVcqsI-KIJCESp43zrNz5HsbwEY8l5rvcwohKGlE_idIFt5IuDTv7vsg_FaCIDeruw0NrXAACnLTwksawsxaCvtY12U0wsI2aC2Sb6V3HL-OLgcN6ZWzZ054L88JllckYnqJB8wCVBzzX2K2sZH3yeS39oRWZOVG6fwXsX4k0fHFx-Fn6KlrBU15pbjMLMn0ow0X3Y8e7FOgfkkph-N7e2SxceXNjrLiumOdclPm9yGSWoGsOJdId53dPvqAsQ",\n          # The root certificate which is used for signing the above certificate (optional).\n          "MIIDrzCCApegAwIBAgIUIK_CYzdq4BLLVXqSclNBgXy6mgswDQYJKoZIhvcNAQELBQAwZjELMAkGA1UEBhMCSlAxDjAMBgNVBAgMBVRva3lvMRAwDgYDVQQKDAdkYWppYWppMRMwEQYDVQQDDApweXRob24tY3d0MSAwHgYJKoZIhvcNAQkBFhFkYWppYWppQGdtYWlsLmNvbTAgFw0yMTEwMDIyMzU0NTZaGA8yMDcxMDkyMDIzNTQ1NlowZjELMAkGA1UEBhMCSlAxDjAMBgNVBAgMBVRva3lvMRAwDgYDVQQKDAdkYWppYWppMRMwEQYDVQQDDApweXRob24tY3d0MSAwHgYJKoZIhvcNAQkBFhFkYWppYWppQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANFg4sw-uPWbPBbkJuohXc89O0gaqG1H2i1wzxxka32XNKIdwrxOJvsB2eALo3q7dTqLKCgzrjdd5N07gi0KzqjoIXIXqKpV5tm0fP5gCzEOWgxySCfBJOJyyvO6WvYXdvukEBnL-48D8RSjQH9fQEju5RG0taFZE-0nQ7n3P0J-Q-OfBUEoRiHvCd8oUx0s-fBpKdfhMAbD1sGAQ9CokUFeWc49em8inNqia5xljBtSYo6_2Zx9eb7B53wvBC0EmtS4SRyksR2emlr6GxMj_EZW7hcTfZCM4V2JYXliuAEdxA0sB7q-WqLg4OvltBQxCBgTTEXRCzxj3XXZy7QyUacCAwEAAaNTMFEwHQYDVR0OBBYEFA9id2cL_Chjv6liRN3HD849TARsMB8GA1UdIwQYMBaAFA9id2cL_Chjv6liRN3HD849TARsMA8GA1UdEwEB_wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAArIej5eJN1OmD3l3ef9QzosCxKThNwqNY55CoSSC3IRl-IAXy9Lvx7cgiliwBgCv99RbXZ1ZnptTHC_1kzMzPhPg9pGKDowFP-rywaB9-NTuHTWQ4hkKDsru5dpf75ILNI5PTUi1iiBM7TdgSerpEVroUWZiOpGAdlKkmE1h4gkR6eQY9Q0IvVXwagy_PPoQ1XO1i5Hyg3aXeDZBgkE7AuW9uxtYQHzg8JG2TNko_yp497yf_Ew4t6KzGDhSa8L1euMPtclALDWFhgl6WmYsHOqAOsyZOLwpsifWa533wI9mtTvLEg8TFKMOdU0sbAoQSbrrI9m4QS7mzDLchngj3E"\n        ],\n        "alg": "ES256"\n    })\n\n# The recipient can specify trusted CAs as follows:\ndecoder = CWT.new(ca_certs="/path/to/cacerts.pem")\ndecoded = decoder.decode(token, public_key)\nassert 1 in decoded and decoded[1] == "coaps://as.example"\n```\n\n### CWT for EUDCC (EU Digital COVID Certificate)\n\nPython CWT supports [Electronic Health Certificate Specification](https://github.com/ehn-dcc-development/hcert-spec/blob/main/hcert_spec.md)\nand [EUDCC (EU Digital COVID Certificate)](https://ec.europa.eu/info/live-work-travel-eu/coronavirus-response/safe-covid-19-vaccines-europeans/eu-digital-covid-certificate_en) compliant with [Technical Specifications for Digital Green Certificates Volume 1](https://ec.europa.eu/health/sites/default/files/ehealth/docs/digital-green-certificates_v1_en.pdf)\n\nA following example shows how to verify an EUDCC:\n\n```py\nimport cwt\nfrom cwt import load_pem_hcert_dsc\n\n# A DSC(Document Signing Certificate) issued by a CSCA\n# (Certificate Signing Certificate Authority) quoted from:\n# https://github.com/eu-digital-green-certificates/dgc-testdata/blob/main/AT/2DCode/raw/1.json\ndsc = "-----BEGIN CERTIFICATE-----\\nMIIBvTCCAWOgAwIBAgIKAXk8i88OleLsuTAKBggqhkjOPQQDAjA2MRYwFAYDVQQDDA1BVCBER0MgQ1NDQSAxMQswCQYDVQQGEwJBVDEPMA0GA1UECgwGQk1TR1BLMB4XDTIxMDUwNTEyNDEwNloXDTIzMDUwNTEyNDEwNlowPTERMA8GA1UEAwwIQVQgRFNDIDExCzAJBgNVBAYTAkFUMQ8wDQYDVQQKDAZCTVNHUEsxCjAIBgNVBAUTATEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASt1Vz1rRuW1HqObUE9MDe7RzIk1gq4XW5GTyHuHTj5cFEn2Rge37+hINfCZZcozpwQKdyaporPUP1TE7UWl0F3o1IwUDAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0OBBYEFO49y1ISb6cvXshLcp8UUp9VoGLQMB8GA1UdIwQYMBaAFP7JKEOflGEvef2iMdtopsetwGGeMAoGCCqGSM49BAMCA0gAMEUCIQDG2opotWG8tJXN84ZZqT6wUBz9KF8D+z9NukYvnUEQ3QIgdBLFSTSiDt0UJaDF6St2bkUQuVHW6fQbONd731/M4nc=\\n-----END CERTIFICATE-----"\n\n# An EUDCC (EU Digital COVID Certificate) quoted from:\n# https://github.com/eu-digital-green-certificates/dgc-testdata/blob/main/AT/2DCode/raw/1.json\neudcc = bytes.fromhex(\n    "d2844da20448d919375fc1e7b6b20126a0590133a4041a61817ca0061a60942ea001624154390103a101a4617681aa62646e01626d616d4f52472d3130303033303231356276706a313131393334393030376264746a323032312d30322d313862636f624154626369783155524e3a555643493a30313a41543a31303830373834334639344145453045453530393346424332353442443831332342626d706c45552f312f32302f31353238626973781b4d696e6973747279206f66204865616c74682c20417573747269616273640262746769383430353339303036636e616da463666e74754d5553544552465241553c474f455353494e47455262666e754d7573746572667261752d47c3b6c39f696e67657263676e74684741425249454c4562676e684761627269656c656376657265312e302e3063646f626a313939382d30322d323658405812fce67cb84c3911d78e3f61f890d0c80eb9675806aebed66aa2d0d0c91d1fc98d7bcb80bf00e181806a9502e11b071325901bd0d2c1b6438747b8cc50f521"\n)\n\npublic_key = load_pem_hcert_dsc(dsc)\ndecoded = cwt.decode(eudcc, keys=[public_key])\nclaims = Claims.new(decoded)\n# claims.hcert[1] ==\n# {\n#     \'v\': [\n#         {\n#             \'dn\': 1,\n#             \'ma\': \'ORG-100030215\',\n#             \'vp\': \'1119349007\',\n#             \'dt\': \'2021-02-18\',\n#             \'co\': \'AT\',\n#             \'ci\': \'URN:UVCI:01:AT:10807843F94AEE0EE5093FBC254BD813#B\',\n#             \'mp\': \'EU/1/20/1528\',\n#             \'is\': \'Ministry of Health, Austria\',\n#             \'sd\': 2,\n#             \'tg\': \'840539006\',\n#         }\n#     ],\n#     \'nam\': {\n#         \'fnt\': \'MUSTERFRAU<GOESSINGER\',\n#         \'fn\': \'Musterfrau-Gößinger\',\n#         \'gnt\': \'GABRIELE\',\n#         \'gn\': \'Gabriele\',\n#     },\n#     \'ver\': \'1.0.0\',\n#     \'dob\': \'1998-02-26\',\n# }\n```\n\n## COSE Usage Examples\n\nFollowings are typical and basic examples which create various types of COSE messages, verify and decode them.\n\nSee [API Reference](https://python-cwt.readthedocs.io/en/stable/api.html#cwt.COSE) and\n[COSE Usage Examples on document](https://python-cwt.readthedocs.io/en/stable/cose_usage.html) for more details.\n\n### COSE MAC0\n\nCreate a COSE MAC0 message, verify and decode it as follows:\n\n```py\nfrom cwt import COSE, COSEKey\n\nmac_key = COSEKey.from_symmetric_key(alg="HS256", kid="01")\nctx = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True)\nencoded = ctx.encode_and_mac(b"Hello world!", mac_key)\nassert b"Hello world!" == ctx.decode(encoded, mac_key)\n```\n\nFollowing two samples are other ways of writing the above example:\n\n```py\nfrom cwt import COSE, COSEKey\n\nmac_key = COSEKey.from_symmetric_key(alg="HS256", kid="01")\nctx = COSE.new()\nencoded = ctx.encode_and_mac(\n    b"Hello world!",\n    mac_key,\n    protected={"alg": "HS256"},\n    unprotected={"kid": "01"},\n)\nassert b"Hello world!" == ctx.decode(encoded, mac_key)\n```\n\n```py\nfrom cwt import COSE, COSEKey\n\nmac_key = COSEKey.from_symmetric_key(alg="HS256", kid="01")\nctx = COSE.new()\nencoded = ctx.encode_and_mac(\n    b"Hello world!",\n    mac_key,\n    protected={1: 5},\n    unprotected={4: b"01"},\n)\nassert b"Hello world!" == ctx.decode(encoded, mac_key)\n```\n\n### COSE MAC\n\n#### Direct Key Distribution for MAC\n\nThe direct key distribution shares a MAC key between the sender and the recipient that is used directly.\nThe follwing example shows the simplest way to make a COSE MAC message, verify and decode it with the direct\nkey distribution method.\n\n```py\nfrom cwt import COSE, COSEKey, Recipient\n\n# The sender makes a COSE MAC message as follows:\nmac_key = COSEKey.from_symmetric_key(alg="HS512", kid="01")\nr = Recipient.from_jwk({"alg": "direct"})\nr.apply(mac_key)\nctx = COSE.new()\nencoded = ctx.encode_and_mac(b"Hello world!", mac_key, recipients=[r])\n\n# The recipient has the same MAC key and can verify and decode it:\nassert b"Hello world!" == ctx.decode(encoded, mac_key)\n```\n\n#### Direct Key with KDF for MAC\n\n\n```py\nfrom secrets import token_bytes\nfrom cwt import COSE, COSEKey, Recipient\n\nshared_material = token_bytes(32)\nshared_key = COSEKey.from_symmetric_key(shared_material, kid="01")\n\n# The sender side:\nr = Recipient.from_jwk(\n    {\n        "kty": "oct",\n        "alg": "direct+HKDF-SHA-256",\n    },\n)\nmac_key = r.apply(shared_key, context={"alg": "HS256"})\nctx = COSE.new(alg_auto_inclusion=True)\nencoded = ctx.encode_and_mac(\n    b"Hello world!",\n    key=mac_key,\n    recipients=[r],\n)\n\n# The recipient side:\nassert b"Hello world!" == ctx.decode(encoded, shared_key, context={"alg": "HS256"})\n```\n\n#### AES Key Wrap for MAC\n\nThe AES key wrap algorithm can be used to wrap a MAC key as follows:\n\n```py\nfrom cwt import COSE, COSEKey, Recipient\n\n# The sender side:\nmac_key = COSEKey.from_symmetric_key(alg="HS512")\nr = Recipient.from_jwk(\n    {\n        "kid": "01",\n        "alg": "A128KW",\n        "k": "hJtXIZ2uSN5kbQfbtTNWbg",  # A shared wrapping key\n    },\n)\nr.apply(mac_key)\nctx = COSE.new(alg_auto_inclusion=True)\nencoded = ctx.encode_and_mac(b"Hello world!", key=mac_key, recipients=[r])\n\n# The recipient side:\nshared_key = COSEKey.from_jwk(\n    {\n        "kid": "01",\n        "kty": "oct",\n        "alg": "A128KW",\n        "k": "hJtXIZ2uSN5kbQfbtTNWbg",\n    },\n)\nassert b"Hello world!" == ctx.decode(encoded, shared_key)\n```\n\n#### Direct Key Agreement for MAC\n\nThe direct key agreement methods can be used to create a shared secret. A KDF (Key Distribution Function) is then\napplied to the shared secret to derive a key to be used to protect the data.\nThe follwing example shows a simple way to make a COSE Encrypt message, verify and decode it with the direct key\nagreement methods (``ECDH-ES+HKDF-256`` with various curves).\n\n```py\nfrom cwt import COSE, COSEKey, Recipient\n\n# The sender side:\nr = Recipient.from_jwk(\n    {\n        "kty": "EC",\n        "alg": "ECDH-ES+HKDF-256",\n        "crv": "P-256",\n    },\n)\n# The following key is provided by the recipient in advance.\npub_key = COSEKey.from_jwk(\n    {\n        "kid": "01",\n        "kty": "EC",\n        "alg": "ECDH-ES+HKDF-256",\n        "crv": "P-256",\n        "x": "Ze2loSV3wrroKUN_4zhwGhCqo3Xhu1td4QjeQ5wIVR0",\n        "y": "HlLtdXARY_f55A3fnzQbPcm6hgr34Mp8p-nuzQCE0Zw",\n    }\n)\nmac_key = r.apply(recipient_key=pub_key, context={"alg": "HS256"})\nctx = COSE.new(alg_auto_inclusion=True)\nencoded = ctx.encode_and_mac(\n    b"Hello world!",\n    key=mac_key,\n    recipients=[r],\n)\n\n# The recipient side:\n# The following key is the private key of the above pub_key.\npriv_key = COSEKey.from_jwk(\n    {\n        "kid": "01",\n        "kty": "EC",\n        "alg": "ECDH-ES+HKDF-256",\n        "crv": "P-256",\n        "x": "Ze2loSV3wrroKUN_4zhwGhCqo3Xhu1td4QjeQ5wIVR0",\n        "y": "HlLtdXARY_f55A3fnzQbPcm6hgr34Mp8p-nuzQCE0Zw",\n        "d": "r_kHyZ-a06rmxM3yESK84r1otSg-aQcVStkRhA-iCM8",\n    }\n)\n# The enc_key will be derived in decode() with priv_key and\n# the sender\'s public key which is conveyed as the recipient\n# information structure in the COSE Encrypt message (encoded).\nassert b"Hello world!" == ctx.decode(encoded, priv_key, context={"alg": "HS256"})\n```\n\n#### Key Agreement with Key Wrap for MAC\n\n\n```py\nfrom cwt import COSE, COSEKey, Recipient\n\n# The sender side:\nmac_key = COSEKey.from_symmetric_key(alg="HS256")\nr = Recipient.from_jwk(\n    {\n        "kty": "EC",\n        "alg": "ECDH-SS+A128KW",\n        "crv": "P-256",\n        "x": "7cvYCcdU22WCwW1tZXR8iuzJLWGcd46xfxO1XJs-SPU",\n        "y": "DzhJXgz9RI6TseNmwEfLoNVns8UmvONsPzQDop2dKoo",\n        "d": "Uqr4fay_qYQykwcNCB2efj_NFaQRRQ-6fHZm763jt5w",\n    }\n)\npub_key = COSEKey.from_jwk(\n    {\n        "kid": "meriadoc.brandybuck@buckland.example",\n        "kty": "EC",\n        "crv": "P-256",\n        "x": "Ze2loSV3wrroKUN_4zhwGhCqo3Xhu1td4QjeQ5wIVR0",\n        "y": "HlLtdXARY_f55A3fnzQbPcm6hgr34Mp8p-nuzQCE0Zw",\n    }\n)\nr.apply(mac_key, recipient_key=pub_key, context={"alg": "HS256"})\nctx = COSE.new(alg_auto_inclusion=True)\nencoded = ctx.encode_and_mac(\n    b"Hello world!",\n    key=mac_key,\n    recipients=[r],\n)\n\n# The recipient side:\npriv_key = COSEKey.from_jwk(\n    {\n        "kid": "meriadoc.brandybuck@buckland.example",\n        "kty": "EC",\n        "crv": "P-256",\n        "alg": "ECDH-SS+A128KW",\n        "x": "Ze2loSV3wrroKUN_4zhwGhCqo3Xhu1td4QjeQ5wIVR0",\n        "y": "HlLtdXARY_f55A3fnzQbPcm6hgr34Mp8p-nuzQCE0Zw",\n        "d": "r_kHyZ-a06rmxM3yESK84r1otSg-aQcVStkRhA-iCM8",\n    }\n)\nassert b"Hello world!" == ctx.decode(encoded, priv_key, context={"alg": "HS256"})\n```\n\n\n### COSE Encrypt0\n\nCreate a COSE Encrypt0 message, verify and decode it as follows:\n\n```py\nfrom cwt import COSE, COSEKey\n\nenc_key = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305", kid="01")\nctx = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True)\nencoded = ctx.encode_and_encrypt(b"Hello world!", enc_key)\ndecoded = ctx.decode(encoded, enc_key)\n```\n\n### COSE Encrypt\n\n#### Direct Key Distribution for encryption\n\nThe direct key distribution shares a MAC key between the sender and the recipient that is used directly.\nThe follwing example shows the simplest way to make a COSE MAC message, verify and decode it with the direct\nkey distribution method.\n\n```py\nfrom cwt import COSE, COSEKey, Recipient\n\nenc_key = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305", kid="01")\n\n# The sender side:\nnonce = enc_key.generate_nonce()\nr = Recipient.from_jwk({"alg": "direct"})\nr.apply(enc_key)\nctx = COSE.new()\nencoded = ctx.encode_and_encrypt(\n    b"Hello world!",\n    enc_key,\n    nonce=nonce,\n    recipients=[r],\n)\n\n# The recipient side:\nassert b"Hello world!" == ctx.decode(encoded, enc_key)\n```\n\n#### Direct Key with KDF for encryption\n\n\n```py\nfrom cwt import COSE, COSEKey, Recipient\n\nshared_material = token_bytes(32)\nshared_key = COSEKey.from_symmetric_key(shared_material, kid="01")\n\n# The sender side:\nr = Recipient.from_jwk(\n    {\n        "kty": "oct",\n        "alg": "direct+HKDF-SHA-256",\n    },\n)\nenc_key = r.apply(shared_key, context={"alg": "A256GCM"})\nctx = COSE.new(alg_auto_inclusion=True)\nencoded = ctx.encode_and_encrypt(\n    b"Hello world!",\n    key=enc_key,\n    recipients=[r],\n)\n# The recipient side:\nassert b"Hello world!" == ctx.decode(encoded, shared_key, context={"alg": "A256GCM"})\n```\n\n#### AES Key Wrap for encryption\n\nThe AES key wrap algorithm can be used to wrap a MAC key as follows:\n\n```py\nfrom cwt import COSE, COSEKey, Recipient\n\n# The sender side:\nr = Recipient.from_jwk(\n    {\n        "kid": "01",\n        "kty": "oct",\n        "alg": "A128KW",\n        "k": "hJtXIZ2uSN5kbQfbtTNWbg",  # A shared wrapping key\n    },\n)\nenc_key = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305")\nr.apply(enc_key)\nctx = COSE.new(alg_auto_inclusion=True)\nencoded = ctx.encode_and_encrypt(b"Hello world!", key=enc_key, recipients=[r])\n\n# The recipient side:\nshared_key = COSEKey.from_jwk(\n    {\n        "kid": "01",\n        "kty": "oct",\n        "alg": "A128KW",\n        "k": "hJtXIZ2uSN5kbQfbtTNWbg",\n    },\n)\nassert b"Hello world!" == ctx.decode(encoded, shared_key)\n```\n\n#### Direct Key Agreement for encryption\n\nThe direct key agreement methods can be used to create a shared secret. A KDF (Key Distribution Function) is then\napplied to the shared secret to derive a key to be used to protect the data.\nThe follwing example shows a simple way to make a COSE Encrypt message, verify and decode it with the direct key\nagreement methods (``ECDH-ES+HKDF-256`` with various curves).\n\n```py\nfrom cwt import COSE, COSEKey, Recipient\n\n# The sender side:\nr = Recipient.from_jwk(\n    {\n        "kty": "OKP",\n        "alg": "ECDH-ES+HKDF-256",\n        "crv": "X25519",\n    },\n)\npub_key = COSEKey.from_jwk(\n    {\n        "kid": "01",\n        "kty": "OKP",\n        "alg": "ECDH-ES+HKDF-256",\n        "crv": "X25519",\n        "x": "y3wJq3uXPHeoCO4FubvTc7VcBuqpvUrSvU6ZMbHDTCI",\n    }\n)\nenc_key = r.apply(recipient_key=pub_key, context={"alg": "A128GCM"})\nctx = COSE.new(alg_auto_inclusion=True)\nencoded = ctx.encode_and_encrypt(\n    b"Hello world!",\n    key=enc_key,\n    recipients=[r],\n)\n\n# The recipient side:\npriv_key = COSEKey.from_jwk(\n    {\n        "kid": "01",\n        "kty": "OKP",\n        "alg": "ECDH-ES+HKDF-256",\n        "crv": "X25519",\n        "x": "y3wJq3uXPHeoCO4FubvTc7VcBuqpvUrSvU6ZMbHDTCI",\n        "d": "vsJ1oX5NNi0IGdwGldiac75r-Utmq3Jq4LGv48Q_Qc4",\n    }\n)\nassert b"Hello world!" == ctx.decode(encoded, priv_key, context={"alg": "A128GCM"})\n```\n\n#### Key Agreement with Key Wrap for encryption\n\n```py\nfrom cwt import COSE, COSEKey, Recipient\n\n# The sender side:\nenc_key = COSEKey.from_symmetric_key(alg="A128GCM")\nnonce = enc_key.generate_nonce()\nr = Recipient.from_jwk(\n    {\n        "kty": "EC",\n        "alg": "ECDH-SS+A128KW",\n        "crv": "P-256",\n        "x": "7cvYCcdU22WCwW1tZXR8iuzJLWGcd46xfxO1XJs-SPU",\n        "y": "DzhJXgz9RI6TseNmwEfLoNVns8UmvONsPzQDop2dKoo",\n        "d": "Uqr4fay_qYQykwcNCB2efj_NFaQRRQ-6fHZm763jt5w",\n    }\n)\npub_key = COSEKey.from_jwk(\n    {\n        "kid": "meriadoc.brandybuck@buckland.example",\n        "kty": "EC",\n        "crv": "P-256",\n        "x": "Ze2loSV3wrroKUN_4zhwGhCqo3Xhu1td4QjeQ5wIVR0",\n        "y": "HlLtdXARY_f55A3fnzQbPcm6hgr34Mp8p-nuzQCE0Zw",\n    }\n)\nr.apply(enc_key, recipient_key=pub_key, context={"alg": "A128GCM"})\nctx = COSE.new(alg_auto_inclusion=True)\nencoded = ctx.encode_and_encrypt(\n    b"Hello world!",\n    key=enc_key,\n    nonce=nonce,\n    recipients=[r],\n)\n\n# The recipient side:\npriv_key = COSEKey.from_jwk(\n    {\n        "kid": "meriadoc.brandybuck@buckland.example",\n        "kty": "EC",\n        "alg": "ECDH-SS+A128KW",\n        "crv": "P-256",\n        "x": "Ze2loSV3wrroKUN_4zhwGhCqo3Xhu1td4QjeQ5wIVR0",\n        "y": "HlLtdXARY_f55A3fnzQbPcm6hgr34Mp8p-nuzQCE0Zw",\n        "d": "r_kHyZ-a06rmxM3yESK84r1otSg-aQcVStkRhA-iCM8",\n    }\n)\nassert b"Hello world!" == ctx.decode(encoded, priv_key, context={"alg": "A128GCM"})\n```\n\n### COSE Signature1\n\nCreate a COSE Signature1 message, verify and decode it as follows:\n\n```py\nfrom cwt import COSE, COSEKey, Signer\n\n# The sender side:\nsigner = Signer.new(\n    cose_key=COSEKey.from_jwk(\n        {\n            "kid": "01",\n            "kty": "EC",\n            "crv": "P-256",\n            "x": "usWxHK2PmfnHKwXPS54m0kTcGJ90UiglWiGahtagnv8",\n            "y": "IBOL-C3BttVivg-lSreASjpkttcsz-1rb7btKLv8EX4",\n            "d": "V8kgd2ZBRuh2dgyVINBUqpPDr7BOMGcF22CQMIUHtNM",\n        }\n    ),\n    protected={"alg": "ES256"},\n    unprotected={"kid": "01"},\n)\nctx = COSE.new()\nencoded = ctx.encode_and_sign(b"Hello world!", signers=[signer])\n\n# The recipient side:\npub_key = COSEKey.from_jwk(\n    {\n        "kid": "01",\n        "kty": "EC",\n        "crv": "P-256",\n        "x": "usWxHK2PmfnHKwXPS54m0kTcGJ90UiglWiGahtagnv8",\n        "y": "IBOL-C3BttVivg-lSreASjpkttcsz-1rb7btKLv8EX4",\n    }\n)\nassert b"Hello world!" == ctx.decode(encoded, pub_key)\n```\n\n### COSE Signature\n\nCreate a COSE Signature message, verify and decode it as follows:\n\n```py\nfrom cwt import COSE, COSEKey, Signer\n\n# The sender side:\nsigner = Signer.new(\n    cose_key=COSEKey.from_jwk(\n        {\n            "kid": "01",\n            "kty": "EC",\n            "crv": "P-256",\n            "x": "usWxHK2PmfnHKwXPS54m0kTcGJ90UiglWiGahtagnv8",\n            "y": "IBOL-C3BttVivg-lSreASjpkttcsz-1rb7btKLv8EX4",\n            "d": "V8kgd2ZBRuh2dgyVINBUqpPDr7BOMGcF22CQMIUHtNM",\n        }\n    ),\n    protected={1: -7},\n    unprotected={4: b"01"},\n)\nctx = COSE.new()\nencoded = ctx.encode_and_sign(b"Hello world!", signers=[signer])\n\n# The recipient side:\npub_key = COSEKey.from_jwk(\n    {\n        "kid": "01",\n        "kty": "EC",\n        "crv": "P-256",\n        "x": "usWxHK2PmfnHKwXPS54m0kTcGJ90UiglWiGahtagnv8",\n        "y": "IBOL-C3BttVivg-lSreASjpkttcsz-1rb7btKLv8EX4",\n    }\n)\nassert b"Hello world!" == ctx.decode(encoded, pub_key)\n```\n## API Reference\n\nSee [Documentation](https://python-cwt.readthedocs.io/en/stable/api.html).\n\n## Supported CWT Claims\n\nSee [Documentation](https://python-cwt.readthedocs.io/en/stable/claims.html).\n\n## Supported COSE Algorithms\n\nSee [Documentation](https://python-cwt.readthedocs.io/en/stable/algorithms.html).\n\n## Referenced Specifications\n\nPython CWT is (partially) compliant with following specifications:\n\n- [RFC8152: CBOR Object Signing and Encryption (COSE)](https://tools.ietf.org/html/rfc8152)\n- [RFC8230: Using RSA Algorithms with COSE Messages](https://tools.ietf.org/html/rfc8230)\n- [RFC8392: CBOR Web Token (CWT)](https://tools.ietf.org/html/rfc8392)\n- [RFC8747: Proof-of-Possession Key Semantics for CBOR Web Tokens (CWTs)](https://tools.ietf.org/html/rfc8747)\n- [RFC8812: COSE and JOSE Registrations for Web Authentication (WebAuthn) Algorithms](https://tools.ietf.org/html/rfc8812)\n- [Electronic Health Certificate Specification](https://github.com/ehn-dcc-development/hcert-spec/blob/main/hcert_spec.md)\n- [Technical Specifications for Digital Green Certificates Volume 1](https://ec.europa.eu/health/sites/default/files/ehealth/docs/digital-green-certificates_v1_en.pdf)\n\n## Tests\n\nYou can run tests from the project root after cloning with:\n\n```sh\n$ tox\n```\n\n## Contributing\n\nWe welcome all kind of contributions, filing issues, suggesting new features or sending PRs.\n',
    'author': 'Ajitomi Daisuke',
    'author_email': 'dajiaji@gmail.com',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/dajiaji/cwt',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'extras_require': extras_require,
    'python_requires': '>=3.6.1,<4.0.0',
}


setup(**setup_kwargs)
