Skip to content

Commit afcc7e4

Browse files
authored
Merge pull request #290 from dajiaji/drop-support-for-recipient-from_jwk
Drop support for Recipient.from_jwk.
2 parents 390d187 + 9b95636 commit afcc7e4

30 files changed

Lines changed: 1300 additions & 3178 deletions

README.md

Lines changed: 71 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,22 @@ $ pip install cwt
2626

2727
And then, you can use it as follows:
2828

29-
```py
29+
**COSE API**
30+
31+
```pycon
32+
>>> from cwt import COSE, COSEKey
33+
>>> ctx = COSE.new()
34+
>>> mac_key = COSEKey.generate_symmetric_key(alg="HS256", kid="01")
35+
>>> encoded = ctx.encode_and_mac(b"Hello world!", mac_key, unprotected={"alg": "HS256"})
36+
>>> encoded.hex()
37+
'd18443a10105a1044230314c48656c6c6f20776f726c642158205d0b144add282ccaac32a02e0d5eec76928ccadf3623271eb48e9464e2ee03b2'
38+
>>> ctx.decode(encoded, mac_key)
39+
b'Hello world!'
40+
```
41+
42+
**CWT API**
43+
44+
```pycon
3045
>>> import cwt
3146
>>> from cwt import COSEKey
3247
>>> key = COSEKey.generate_symmetric_key(alg="HS256", kid="01")
@@ -37,7 +52,9 @@ And then, you can use it as follows:
3752
{1: 'coaps://as.example', 2: 'dajiaji', 7: b'123', 4: 1620088759, 5: 1620085159, 6: 1620085159}
3853
```
3954

40-
See [Documentation](https://python-cwt.readthedocs.io/en/stable/) for details.
55+
Various usage examples are shown in this README.
56+
57+
See [Documentation](https://python-cwt.readthedocs.io/en/stable/) for the details of API specification.
4158

4259
## Index
4360

@@ -89,10 +106,9 @@ pip install cwt
89106

90107
## COSE Usage Examples
91108

92-
Followings are typical and basic examples which create various types of COSE messages, verify and decode them.
109+
Followings are typical and basic examples which encode various types of COSE messages and decode them.
93110

94-
See [API Reference](https://python-cwt.readthedocs.io/en/stable/api.html#cwt.COSE) and
95-
[COSE Usage Examples on document](https://python-cwt.readthedocs.io/en/stable/cose_usage.html) for more details.
111+
See [API Reference](https://python-cwt.readthedocs.io/en/stable/api.html#cwt.COSE).
96112

97113
### COSE MAC0
98114

@@ -167,6 +183,7 @@ mac_key = COSEKey.generate_symmetric_key(alg="HS512", kid="01")
167183

168184
# The sender side:
169185
r = Recipient.new(unprotected={"alg": "direct", "kid": mac_key.kid})
186+
# r = Recipient.new(unprotected={1: -6, 4: mac_key.kid}) # is also acceptable.
170187

171188
sender = COSE.new()
172189
encoded = sender.encode_and_mac(b"Hello world!", mac_key, recipients=[r])
@@ -192,12 +209,12 @@ r = Recipient.new(
192209
"alg": "direct+HKDF-SHA-256",
193210
"salt": "aabbccddeeffgghh",
194211
},
212+
context={"alg": "HS256"},
195213
)
196-
mac_key = r.encode(shared_key.to_bytes(), context={"alg": "HS256"})
197214
sender = COSE.new(alg_auto_inclusion=True)
198215
encoded = sender.encode_and_mac(
199216
b"Hello world!",
200-
mac_key,
217+
shared_key,
201218
recipients=[r],
202219
)
203220

@@ -213,19 +230,17 @@ The AES key wrap algorithm can be used to wrap a MAC key as follows:
213230
```py
214231
from cwt import COSE, COSEKey, Recipient
215232

233+
# The sender side:
234+
mac_key = COSEKey.generate_symmetric_key(alg="HS512")
216235
enc_key = COSEKey.from_jwk(
217236
{
218237
"kty": "oct",
219238
"kid": "01",
220239
"alg": "A128KW",
221240
"k": "hJtXIZ2uSN5kbQfbtTNWbg", # A shared wrapping key
222241
}
223-
);
224-
225-
# The sender side:
226-
mac_key = COSEKey.generate_symmetric_key(alg="HS512")
242+
)
227243
r = Recipient.new(unprotected={"alg": "A128KW"}, sender_key=enc_key)
228-
r.encode(mac_key.to_bytes())
229244
sender = COSE.new(alg_auto_inclusion=True)
230245
encoded = sender.encode_and_mac(b"Hello world!", mac_key, recipients=[r])
231246

@@ -255,10 +270,16 @@ pub_key = COSEKey.from_jwk(
255270
"y": "HlLtdXARY_f55A3fnzQbPcm6hgr34Mp8p-nuzQCE0Zw",
256271
}
257272
)
258-
r = Recipient.new({"alg": "ECDH-ES+HKDF-256"}, recipient_key=pub_key)
259-
mac_key = r.encode(context={"alg": "HS256"})
273+
r = Recipient.new(
274+
unprotected={"alg": "ECDH-ES+HKDF-256"},
275+
recipient_key=pub_key,
276+
context={"alg": "HS256"},
277+
)
260278
sender = COSE.new(alg_auto_inclusion=True)
261-
encoded = sender.encode_and_mac(b"Hello world!", mac_key, recipients=[r])
279+
encoded = sender.encode_and_mac(
280+
b"Hello world!",
281+
recipients=[r],
282+
)
262283

263284
# The recipient side:
264285
# The following key is the private key of the above pub_key.
@@ -286,9 +307,8 @@ assert b"Hello world!" == recipient.decode(encoded, priv_key, context={"alg": "H
286307
```py
287308
from cwt import COSE, COSEKey, Recipient
288309

289-
mac_key = COSEKey.generate_symmetric_key(alg="HS256")
290-
291310
# The sender side:
311+
mac_key = COSEKey.generate_symmetric_key(alg="HS256")
292312
pub_key = COSEKey.from_jwk(
293313
{
294314
"kty": "EC",
@@ -299,8 +319,11 @@ pub_key = COSEKey.from_jwk(
299319
"y": "HlLtdXARY_f55A3fnzQbPcm6hgr34Mp8p-nuzQCE0Zw",
300320
}
301321
)
302-
r = Recipient.new(unprotected={"alg": "ECDH-ES+A128KW"}, recipient_key=pub_key)
303-
r.encode(mac_key.to_bytes(), context={"alg": "HS256"})
322+
r = Recipient.new(
323+
unprotected={"alg": "ECDH-ES+A128KW"},
324+
recipient_key=pub_key,
325+
context={"alg": "HS256"},
326+
)
304327
sender = COSE.new(alg_auto_inclusion=True)
305328
encoded = sender.encode_and_mac(
306329
b"Hello world!",
@@ -416,7 +439,7 @@ enc_key = COSEKey.generate_symmetric_key(alg="ChaCha20/Poly1305", kid="01")
416439
# The sender side:
417440
nonce = enc_key.generate_nonce()
418441
r = Recipient.new(unprotected={"alg": "direct", "kid": enc_key.kid})
419-
# r = Recipient.new(unprotected={1: -6, 4: enc_key.kid}) # is also acceptable
442+
# r = Recipient.new(unprotected={1: -6, 4: enc_key.kid}) # is also acceptable.
420443

421444
sender = COSE.new()
422445
encoded = sender.encode_and_encrypt(
@@ -446,12 +469,12 @@ r = Recipient.new(
446469
"alg": "direct+HKDF-SHA-256",
447470
"salt": "aabbccddeeffgghh",
448471
},
472+
context={"alg": "A256GCM"},
449473
)
450-
enc_key = r.encode(shared_key.to_bytes(), context={"alg": "A256GCM"})
451474
sender = COSE.new(alg_auto_inclusion=True)
452475
encoded = sender.encode_and_encrypt(
453476
b"Hello world!",
454-
key=enc_key,
477+
shared_key,
455478
recipients=[r],
456479
)
457480

@@ -483,7 +506,6 @@ r = Recipient.new(
483506
unprotected={"alg": "A128KW"},
484507
sender_key=wrapping_key,
485508
)
486-
r.encode(enc_key.to_bytes())
487509
sender = COSE.new(alg_auto_inclusion=True)
488510
encoded = sender.encode_and_encrypt(b"Hello world!", key=enc_key, recipients=[r])
489511

@@ -520,12 +542,14 @@ pub_key = COSEKey.from_jwk(
520542
"y": "HlLtdXARY_f55A3fnzQbPcm6hgr34Mp8p-nuzQCE0Zw",
521543
}
522544
)
523-
r = Recipient.new(unprotected={"alg": "ECDH-ES+HKDF-256"}, recipient_key=pub_key)
524-
enc_key = r.encode(context={"alg": "A128GCM"})
545+
r = Recipient.new(
546+
unprotected={"alg": "ECDH-ES+HKDF-256"},
547+
recipient_key=pub_key,
548+
context={"alg": "A128GCM"},
549+
)
525550
sender = COSE.new(alg_auto_inclusion=True)
526551
encoded = sender.encode_and_encrypt(
527552
b"Hello world!",
528-
key=enc_key,
529553
recipients=[r],
530554
)
531555

@@ -572,8 +596,12 @@ s_priv_key = COSEKey.from_jwk(
572596
"d": "Uqr4fay_qYQykwcNCB2efj_NFaQRRQ-6fHZm763jt5w",
573597
}
574598
)
575-
r = Recipient.new(unprotected={"alg": "ECDH-SS+A128KW"}, sender_key=s_priv_key, recipient_key=r_pub_key)
576-
r.encode(enc_key.to_bytes(), context={"alg": "A128GCM"})
599+
r = Recipient.new(
600+
unprotected={"alg": "ECDH-SS+A128KW"},
601+
sender_key=s_priv_key,
602+
recipient_key=r_pub_key,
603+
context={"alg": "A128GCM"},
604+
)
577605
sender = COSE.new(alg_auto_inclusion=True)
578606
encoded = sender.encode_and_encrypt(
579607
b"Hello world!",
@@ -632,7 +660,6 @@ r = Recipient.new(
632660
},
633661
recipient_key=rpk,
634662
)
635-
r.encode(enc_key.to_bytes())
636663
sender = COSE.new()
637664
encoded = sender.encode_and_encrypt(
638665
b"This is the content.",
@@ -729,14 +756,12 @@ assert b"Hello world!" == recipient.decode(encoded, pub_key)
729756

730757
## CWT Usage Examples
731758

732-
Followings are typical and basic examples which create various types of CWTs, verify and decode them.
759+
Followings are typical and basic examples which encode various types of CWTs, verify and decode them.
733760

734761
[CWT API](https://python-cwt.readthedocs.io/en/stable/api.html) in the examples are built
735762
on top of [COSE API](https://python-cwt.readthedocs.io/en/stable/api.html#cwt.COSE).
736763

737-
See [API Reference](https://python-cwt.readthedocs.io/en/stable/api.html) and
738-
[CWT Usage Examples on document](https://python-cwt.readthedocs.io/en/stable/cwt_usage.html)
739-
for more details.
764+
See [API Reference](https://python-cwt.readthedocs.io/en/stable/api.html).
740765

741766
### MACed CWT
742767

@@ -748,7 +773,7 @@ from cwt import Claims, COSEKey
748773

749774
try:
750775
key = COSEKey.generate_symmetric_key(alg="HS256", kid="01")
751-
token = cwt.encode({"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, key)
776+
token = cwt.{"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, key)
752777
decoded = cwt.decode(token, key)
753778

754779
# If you want to treat the result like a JWT;
@@ -777,7 +802,7 @@ import cwt
777802
from cwt import COSEKey
778803

779804
key = COSEKey.generate_symmetric_key(alg="HS256", kid="01")
780-
token = cwt.encode({1: "coaps://as.example", 2: "dajiaji", 7: b"123"}, key)
805+
token = cwt.{1: "coaps://as.example", 2: "dajiaji", 7: b"123"}, key)
781806
decoded = cwt.decode(token, key)
782807
```
783808

@@ -802,7 +827,7 @@ from cwt import COSEKey
802827
# The sender side:
803828
with open("./private_key.pem") as key_file:
804829
private_key = COSEKey.from_pem(key_file.read(), kid="01")
805-
token = cwt.encode(
830+
token = cwt.
806831
{"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, private_key
807832
)
808833

@@ -828,7 +853,7 @@ private_key = COSEKey.from_jwk({
828853
"x": "2E6dX83gqD_D0eAmqnaHe1TC1xuld6iAKXfw2OVATr0",
829854
"d": "L8JS08VsFZoZxGa9JvzYmCWOwg7zaKcei3KZmYsj7dc",
830855
})
831-
token = cwt.encode(
856+
token = cwt.
832857
{"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, private_key
833858
)
834859

@@ -855,7 +880,7 @@ import cwt
855880
from cwt import COSEKey
856881

857882
enc_key = COSEKey.generate_symmetric_key(alg="ChaCha20/Poly1305", kid="01")
858-
token = cwt.encode({"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, enc_key)
883+
token = cwt.{"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, enc_key)
859884
decoded = cwt.decode(token, enc_key)
860885
```
861886

@@ -876,12 +901,12 @@ enc_key = COSEKey.generate_symmetric_key(alg="ChaCha20/Poly1305", kid="enc-01")
876901
# Creates a CWT with ES256 signing.
877902
with open("./private_key.pem") as key_file:
878903
private_key = COSEKey.from_pem(key_file.read(), kid="sig-01")
879-
token = cwt.encode(
904+
token = cwt.
880905
{"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, private_key
881906
)
882907

883908
# Encrypts the signed CWT.
884-
nested = cwt.encode(token, enc_key)
909+
nested = cwt.token, enc_key)
885910

886911
# Decrypts and verifies the nested CWT.
887912
with open("./public_key.pem") as key_file:
@@ -891,7 +916,7 @@ decoded = cwt.decode(nested, [enc_key, public_key])
891916

892917
### CWT with User Settings
893918

894-
The `cwt` in `cwt.encode()` and `cwt.decode()` above is a global `CWT` class instance created
919+
The `cwt` in `cwt.)` and `cwt.decode()` above is a global `CWT` class instance created
895920
with default settings in advance. The default settings are as follows:
896921
- `expires_in`: `3600` seconds. This is the default lifetime in seconds of CWTs.
897922
- `leeway`: `60` seconds. This is the default leeway in seconds for validating `exp` and `nbf`.
@@ -903,7 +928,7 @@ from cwt import COSEKey, CWT
903928

904929
key = COSEKey.generate_symmetric_key(alg="HS256", kid="01")
905930
mycwt = CWT.new(expires_in=3600*24, leeway=10)
906-
token = mycwt.encode({"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, key)
931+
token = mycwt.{"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, key)
907932
decoded = mycwt.decode(token, key)
908933
```
909934

@@ -920,7 +945,7 @@ from cwt import COSEKey
920945
# The sender side:
921946
with open("./private_key.pem") as key_file:
922947
private_key = COSEKey.from_pem(key_file.read(), kid="01")
923-
token = cwt.encode(
948+
token = cwt.
924949
{
925950
1: "coaps://as.example", # iss
926951
2: "dajiaji", # sub
@@ -966,7 +991,7 @@ my_claim_names = {
966991
}
967992

968993
cwt.set_private_claim_names(my_claim_names)
969-
token = cwt.encode(
994+
token = cwt.
970995
{
971996
"iss": "coaps://as.example",
972997
"sub": "dajiaji",
@@ -1010,7 +1035,7 @@ with open("./private_key_of_issuer.pem") as key_file:
10101035
private_key = COSEKey.from_pem(key_file.read(), kid="issuer-01")
10111036

10121037
# Sets the PoP key to a CWT for the presenter.
1013-
token = cwt.encode(
1038+
token = cwt.
10141039
{
10151040
"iss": "coaps://as.example",
10161041
"sub": "dajiaji",
@@ -1090,7 +1115,7 @@ from cwt import Claims, COSEKey
10901115
with open("./private_key_of_cert.pem")) as f:
10911116
private_key = COSEKey.from_pem(f.read(), kid="01")
10921117

1093-
token = cwt.encode(
1118+
token = cwt.
10941119
{"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, private_key
10951120
)
10961121

0 commit comments

Comments
 (0)