A Python implementation of CBOR Web Token (CWT) and CBOR Object Signing and Encryption (COSE).
Project description
Python CWT
A Python implementation of CBOR Web Token (CWT) and CBOR Object Signing and Encryption (COSE).
See Document for details:
- Usage Examples
- API Reference
- Supported CWT Claims
- Supported COSE Algorithms
- Referenced Specifications
Installing
Install with pip:
pip install cwt
Usase
Python CWT is an easy-to-use CWT/COSE library a little bit inspired by PyJWT. If you already know about JSON Web Token (JWT), little knowledge of CBOR, COSE and CWT is required to use this library.
>>> import cwt
>>> from cwt import claims, cose_key
>>> key = cose_key.from_symmetric_key(alg="HS256")
>>> token = cwt.encode({"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, key)
>>> token.hex()
'd18443a10105a05835a60172636f6170733a2f2f61732e6578616d706c65026764616a69616a69'
'0743313233041a609097b7051a609089a7061a609089a758201fad9b0a76803194bd11ca9b9b3c'
'bbf1028005e15321665a768994f38c7127f7'
>>> decoded = cwt.decode(token, key)
>>> decoded
{1: 'coaps://as.example', 2: 'dajiaji', 7: b'123',
4: 1620088759, 5: 1620085159, 6: 1620085159}
>>> readable = claims.from_dict(decoded)
>>> readable.iss
'coaps://as.example'
>>> readable.sub
'dajiaji'
>>> readable.exp
1620088759
Followings are typical and basic examples which create CWT, verify and decode it:
See Usage Examples for details.
MACed CWT
Create a MACed CWT with HS256
, verify and decode it as follows:
import cwt
from cwt import cose_key
key = cose_key.from_symmetric_key(alg="HS256")
token = cwt.encode({"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, key)
decoded = cwt.decode(token, key)
CBOR-like structure (Dict[int, Any]) can also be used as follows:
import cwt
from cwt import cose_key
key = cose_key.from_symmetric_key(alg="HS256")
token = cwt.encode({1: "coaps://as.example", 2: "dajiaji", 7: b"123"}, key)
decoded = cwt.decode(token, key)
MAC algorithms other than HS256
are listed in
Supported COSE Algorithms.
Signed CWT
Create an Ed25519
(Ed25519 for use w/ EdDSA only) key pair:
$ openssl genpkey -algorithm ed25519 -out private_key.pem
$ openssl pkey -in private_key.pem -pubout -out public_key.pem
Create a Signed CWT with Ed25519
, verify and decode it with the key pair as follows:
import cwt
from cwt import cose_key
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())
token = cwt.encode(
{"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, private_key
)
decoded = cwt.decode(token, public_key)
JWKs can also be used instead of the PEM-formatted keys as follows:
import cwt
from cwt import cose_key
private_key = cose_key.from_jwk({
"kty": "OKP",
"d": "L8JS08VsFZoZxGa9JvzYmCWOwg7zaKcei3KZmYsj7dc",
"use": "sig",
"crv": "Ed25519",
"kid": "01",
"x": "2E6dX83gqD_D0eAmqnaHe1TC1xuld6iAKXfw2OVATr0",
"alg": "EdDSA",
})
public_key = cose_key.from_jwk({
"kty": "OKP",
"use": "sig",
"crv": "Ed25519",
"kid": "01",
"x": "2E6dX83gqD_D0eAmqnaHe1TC1xuld6iAKXfw2OVATr0",
})
token = cwt.encode(
{"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, private_key
)
decoded = cwt.decode(token, public_key)
Algorithms other than Ed25519
are listed in
Supported COSE Algorithms.
Encrypted CWT
Create an encrypted CWT with ChaCha20/Poly1305
(ChaCha20/Poly1305 w/ 256-bit key, 128-bit tag),
and decrypt it as follows:
import cwt
from cwt import cose_key
enc_key = cose_key.from_symmetric_key(alg="ChaCha20/Poly1305")
token = cwt.encode({"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, enc_key)
decoded = cwt.decode(token, enc_key)
Algorithms other than ChaCha20/Poly1305
are listed in
Supported COSE Algorithms.
Nested CWT
Create a signed CWT and encrypt it, and then decrypt and verify the nested CWT as follows.
import cwt
from cwt import cose_key
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())
# Creates a CWT with ES256 signing.
token = cwt.encode(
{"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, private_key
)
# Encrypts the signed CWT.
enc_key = cose_key.from_symmetric_key(alg="ChaCha20/Poly1305")
nested = cwt.encode(token, enc_key)
# Decrypts and verifies the nested CWT.
decoded = cwt.decode(nested, [enc_key, public_key])
CWT with PoP key
This library supports Proof-of-Possession Key Semantics for CBOR Web Tokens (CWTs). A CWT can include a PoP key as follows:
On the issuer side:
import cwt
from cwt import cose_key
# Prepares a signing key for CWT in advance.
with open("./private_key_of_issuer.pem") as key_file:
private_key = cose_key.from_pem(key_file.read())
# Sets the PoP key to a CWT for the presenter.
token = cwt.encode(
{
"iss": "coaps://as.example",
"sub": "dajiaji",
"cti": "123",
"cnf": {
"jwk": { # Provided by the CWT presenter.
"kty": "OKP",
"use": "sig",
"crv": "Ed25519",
"kid": "01",
"x": "2E6dX83gqD_D0eAmqnaHe1TC1xuld6iAKXfw2OVATr0",
"alg": "EdDSA",
},
},
},
private_key,
)
# Issues the token to the presenter.
On the CWT presenter side:
import cwt
from cwt import cose_key
# Prepares a private PoP key in advance.
with open("./private_pop_key.pem") as key_file:
pop_key_private = cose_key.from_pem(key_file.read())
# Receives a message (e.g., nonce) from the recipient.
msg = b"could-you-sign-this-message?" # Provided by recipient.
# Signs the message with the private PoP key.
sig = pop_key_private.sign(msg)
# Sends the msg and the sig with the CWT to the recipient.
On the CWT recipient side:
import cwt
from cwt import claims, cose_key
# Prepares the public key of the issuer in advance.
with open("./public_key_of_issuer.pem") as key_file:
public_key = cose_key.from_pem(key_file.read())
# Verifies and decodes the CWT received from the presenter.
raw = cwt.decode(token, public_key)
decoded = claims.from_dict(raw)
# Extracts the PoP key from the CWT.
extracted_pop_key = cose_key.from_dict(decoded.cnf) # = raw[8][1]
# Then, verifies the message sent by the presenter
# with the signature which is also sent by the presenter as follows:
extracted_pop_key.verify(msg, sig)
Usage Examples shows other examples which use other confirmation methods for PoP keys.
Tests
You can run tests from the project root after cloning with:
$ tox
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.