Metadata-Version: 2.1
Name: cwt
Version: 0.1.0
Summary: A Python implementation of CWT (CBOR Web Token) and COSE (CBOR Object Signing and Encryption).
Home-page: https://github.com/dajiaji/python-cwt
Author: AJITOMI Daisuke
Author-email: ajitomi@gmail.com
License: MIT
Keywords: cbor cwt cose security signature encryption token
Platform: UNKNOWN
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Natural Language :: English
Classifier: License :: OSI Approved :: MIT License
Classifier: Topic :: Utilities
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Requires-Python: >=3.6
Description-Content-Type: text/markdown
Requires-Dist: cbor2
Requires-Dist: cryptography (>=3.3.1)
Provides-Extra: dev
Requires-Dist: sphinx ; extra == 'dev'
Requires-Dist: sphinx-rtd-theme ; extra == 'dev'
Requires-Dist: cryptography (>=3.3.1) ; extra == 'dev'
Requires-Dist: pytest (<7.0.0,>=6.0.0) ; extra == 'dev'
Requires-Dist: coverage[toml] (==5.0.4) ; extra == 'dev'
Requires-Dist: mypy ; extra == 'dev'
Provides-Extra: docs
Requires-Dist: sphinx ; extra == 'docs'
Requires-Dist: sphinx-rtd-theme ; extra == 'docs'
Requires-Dist: sphinx-autodoc-typehints (>=1.2.0) ; extra == 'docs'
Provides-Extra: tests
Requires-Dist: pytest (>=6.0.0) ; extra == 'tests'
Requires-Dist: pytest-cov (>=2.0) ; extra == 'tests'
Requires-Dist: coverage[toml] (==5.0.4) ; extra == 'tests'

# Python CWT

A Python (>= 3.6) implementation of CBOR Web Token (CWT) and CBOR Object Signing and Encryption (COSE) compliant with:
- [RFC8392: CBOR Web Token (CWT)](https://tools.ietf.org/html/rfc8392)
- [RFC8152: CBOR Object Signing and Encryption (COSE)](https://tools.ietf.org/html/rfc8152)

## Installing

Install with pip after cloning this repository.

```
pip install .
```

## Usase

Python CWT is easy to use.
If you already know about [JSON Web Token (JWT)](https://tools.ietf.org/html/rfc7519),
little knowledge of [CBOR](https://tools.ietf.org/html/rfc7049), [COSE](https://tools.ietf.org/html/rfc8152)
and [CWT](https://tools.ietf.org/html/rfc8392) is required to use this library.

Followings are basic examples which create CWT, verify and decode it:

- [MACed CWT](#maced-cwt)
- [Signed CWT](#signed-cwt)
- [Encrypted CWT](#encrypted-cwt)
- [Nested CWT](#nested-cwt)

### MACed CWT

Create a MACed CWT, verify and decode it as follows:

```py
import cwt
from cwt import cose_key, claims

key = cose_key.from_symmetric_key("mysecretpassword")  # Default algorithm is "HMAC256/256"
encoded = cwt.encode_and_mac(
    claims.from_json(
        {"iss": "https://as.example", "sub": "dajiaji", "cti": "123"}
    ),
    key,
)
decoded = cwt.decode(encoded, key)
```

CBOR-like structure (Dict[int, Any]) can also be used as follows:

```py
import cwt

key = cwt.cose_key.from_symmetric_key("mysecretpassword")
encoded = cwt.encode_and_mac(
    {1: "https://as.example", 2: "dajiaji", 7: b"123"},
    key,
)
decoded = cwt.decode(encoded, key)
```

### Signed CWT

Create an `ES256` (ECDSA with SHA-256) key pair:

```sh
$ openssl ecparam -genkey -name prime256v1 -noout -out private_key.pem
$ openssl ec -in private_key.pem -pubout -out public_key.pem
```

Create a Signed CWT, verify and decode it with the key pair as follows:

```py
import cwt
from cwt import cose_key, claims

# Load PEM-formatted keys as COSE keys.
with open("./private_key.pem") as key_file:
    private_key = cose_key.from_pem(key_file.read())
with open("./public_key.pem") as key_file:
    public_key = cose_key.from_pem(key_file.read())

# Encode with ES256 signing.
encoded = cwt.encode_and_sign(
    claims.from_json(
        {"iss": "https://as.example", "sub":"dajiaji", "cti":"123"}
    ),
    private_key
)

# Verify and decode.
decoded = cwt.decode(encoded, public_key)
```

Algorithms other than `ES256` are also supported. The following is an example of `Ed25519`:

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

```py
import cwt
from cwt import cose_key, claims

# Load PEM-formatted keys as COSE keys.
with open("./private_key.pem") as key_file:
    private_key = cose_key.from_pem(key_file.read())
with open("./public_key.pem") as key_file:
    public_key = cose_key.from_pem(key_file.read())

# Encode with Ed25519 signing.
encoded = cwt.encode_and_encrypt(
    claims.from_json(
        {"iss": "https://as.example", "sub": "dajiaji", "cti": "123"}
    ),
    private_key,
)

# Verify and decode.
decoded = cwt.decode(encoded, public_key)
```

### Encrypted CWT

Create an encrypted CWT with `AES-CCM-16-64-256` (AES-CCM mode using 128-bit symmetric key),
and decrypt it as follows:

```py
from secrets import token_bytes
import cwt
from cwt import cose_key, claims

nonce = token_bytes(13)
mysecret = token_bytes(32)
enc_key = cose_key.from_symmetric_key(mysecret, alg="AES-CCM-16-64-256")
encoded = cwt.encode_and_encrypt(
    claims.from_json(
        {"iss": "https://as.example", "sub": "dajiaji", "cti": "123"}
    ),
    enc_key,
    nonce=nonce,
)
decoded = cwt.decode(encoded, enc_key)
```

### Nested CWT

Create a signed CWT and encrypt it, and then decrypt and verify the nested CWT as follows.

```py
from secrets import token_bytes
import cwt
from cwt import cose_key, claims

# Load PEM-formatted keys as COSE keys.
with open("./private_key.pem") as key_file:
    private_key = cose_key.from_pem(key_file.read())
with open("./public_key.pem") as key_file:
    public_key = cose_key.from_pem(key_file.read())

# Encode with ES256 signing.
encoded = cwt.encode_and_sign(
    claims.from_json(
        {"iss": "https://as.example", "sub":"dajiaji", "cti":"123"}
    ),
    private_key
)

# Encrypt the signed CWT.
nonce = token_bytes(13)
mysecret = token_bytes(32)
enc_key = cose_key.from_symmetric_key(mysecret, alg="AES-CCM-16-64-256")
nested = cwt.encode_and_encrypt(encoded, enc_key, nonce=nonce)

# Decrypt and verify the nested CWT.
decoded = cwt.decode(nested, [enc_key, public_key])
```

## Tests

You can run tests from the project root after cloning with:

```sh
$ tox
```


