Skip to content

Commit 85f0f2a

Browse files
authored
Add generate_symmetric_key as a COSEKey classmethod.
Add generate_symmetric_key as a COSEKey classmethod.
2 parents 21eff82 + d324b15 commit 85f0f2a

5 files changed

Lines changed: 76 additions & 49 deletions

File tree

README.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ And then, you can use it as follows:
2929
```py
3030
>>> import cwt
3131
>>> from cwt import COSEKey
32-
>>> key = COSEKey.from_symmetric_key(alg="HS256", kid="01")
32+
>>> key = COSEKey.generate_symmetric_key(alg="HS256", kid="01")
3333
>>> token = cwt.encode({"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, key)
3434
>>> token.hex()
3535
'd18443a10105a05835a60172636f6170733a2f2f61732e657861'...
@@ -101,7 +101,7 @@ Create a COSE MAC0 message, verify and decode it as follows:
101101
```py
102102
from cwt import COSE, COSEKey
103103

104-
mac_key = COSEKey.from_symmetric_key(alg="HS256", kid="01")
104+
mac_key = COSEKey.generate_symmetric_key(alg="HS256", kid="01")
105105

106106
# The sender side:
107107
sender = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True)
@@ -117,7 +117,7 @@ Following two samples are other ways of writing the above example:
117117
```py
118118
from cwt import COSE, COSEKey
119119

120-
mac_key = COSEKey.from_symmetric_key(alg="HS256", kid="01")
120+
mac_key = COSEKey.generate_symmetric_key(alg="HS256", kid="01")
121121

122122
# The sender side:
123123
sender = COSE.new()
@@ -136,7 +136,7 @@ assert b"Hello world!" == recipient.decode(encoded, mac_key)
136136
```py
137137
from cwt import COSE, COSEKey
138138

139-
mac_key = COSEKey.from_symmetric_key(alg="HS256", kid="01")
139+
mac_key = COSEKey.generate_symmetric_key(alg="HS256", kid="01")
140140

141141
# The sender side:
142142
sender = COSE.new()
@@ -163,7 +163,7 @@ key distribution method.
163163
```py
164164
from cwt import COSE, COSEKey, Recipient
165165

166-
mac_key = COSEKey.from_symmetric_key(alg="HS512", kid="01")
166+
mac_key = COSEKey.generate_symmetric_key(alg="HS512", kid="01")
167167

168168
# The sender side:
169169
r = Recipient.from_jwk({"alg": "direct"})
@@ -216,7 +216,7 @@ The AES key wrap algorithm can be used to wrap a MAC key as follows:
216216
from cwt import COSE, COSEKey, Recipient
217217

218218
# The sender side:
219-
mac_key = COSEKey.from_symmetric_key(alg="HS512")
219+
mac_key = COSEKey.generate_symmetric_key(alg="HS512")
220220
r = Recipient.from_jwk(
221221
{
222222
"kty": "oct",
@@ -354,7 +354,7 @@ Create a COSE Encrypt0 message and decrypt it as follows:
354354
```py
355355
from cwt import COSE, COSEKey
356356

357-
enc_key = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305", kid="01")
357+
enc_key = COSEKey.generate_symmetric_key(alg="ChaCha20/Poly1305", kid="01")
358358

359359
# The sender side:
360360
nonce = enc_key.generate_nonce()
@@ -431,7 +431,7 @@ key distribution method.
431431
```py
432432
from cwt import COSE, COSEKey, Recipient
433433

434-
enc_key = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305", kid="01")
434+
enc_key = COSEKey.generate_symmetric_key(alg="ChaCha20/Poly1305", kid="01")
435435

436436
# The sender side:
437437
nonce = enc_key.generate_nonce()
@@ -489,7 +489,7 @@ The AES key wrap algorithm can be used to wrap a MAC key as follows:
489489
from cwt import COSE, COSEKey, Recipient
490490

491491
# A key to be wrapped
492-
enc_key = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305")
492+
enc_key = COSEKey.generate_symmetric_key(alg="ChaCha20/Poly1305")
493493

494494
# The sender side:
495495
r = Recipient.from_jwk(
@@ -623,7 +623,7 @@ Create a COSE-HPKE Encrypt message and decrypt it as follows:
623623
from cwt import COSE, COSEKey, Recipient
624624

625625
# The sender side:
626-
enc_key = COSEKey.from_symmetric_key(alg="A128GCM")
626+
enc_key = COSEKey.generate_symmetric_key(alg="A128GCM")
627627
rpk = COSEKey.from_jwk(
628628
{
629629
"kty": "EC",
@@ -761,7 +761,7 @@ import cwt
761761
from cwt import Claims, COSEKey
762762

763763
try:
764-
key = COSEKey.from_symmetric_key(alg="HS256", kid="01")
764+
key = COSEKey.generate_symmetric_key(alg="HS256", kid="01")
765765
token = cwt.encode({"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, key)
766766
decoded = cwt.decode(token, key)
767767

@@ -790,7 +790,7 @@ A raw CWT structure (Dict[int, Any]) can also be used as follows:
790790
import cwt
791791
from cwt import COSEKey
792792

793-
key = COSEKey.from_symmetric_key(alg="HS256", kid="01")
793+
key = COSEKey.generate_symmetric_key(alg="HS256", kid="01")
794794
token = cwt.encode({1: "coaps://as.example", 2: "dajiaji", 7: b"123"}, key)
795795
decoded = cwt.decode(token, key)
796796
```
@@ -868,7 +868,7 @@ Create an encrypted CWT with `ChaCha20/Poly1305` and decrypt it as follows:
868868
import cwt
869869
from cwt import COSEKey
870870

871-
enc_key = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305", kid="01")
871+
enc_key = COSEKey.generate_symmetric_key(alg="ChaCha20/Poly1305", kid="01")
872872
token = cwt.encode({"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, enc_key)
873873
decoded = cwt.decode(token, enc_key)
874874
```
@@ -885,7 +885,7 @@ import cwt
885885
from cwt import COSEKey
886886

887887
# A shared encryption key.
888-
enc_key = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305", kid="enc-01")
888+
enc_key = COSEKey.generate_symmetric_key(alg="ChaCha20/Poly1305", kid="enc-01")
889889

890890
# Creates a CWT with ES256 signing.
891891
with open("./private_key.pem") as key_file:
@@ -915,7 +915,7 @@ If you want to change the settings, you can create your own `CWT` class instance
915915
```py
916916
from cwt import COSEKey, CWT
917917

918-
key = COSEKey.from_symmetric_key(alg="HS256", kid="01")
918+
key = COSEKey.generate_symmetric_key(alg="HS256", kid="01")
919919
mycwt = CWT.new(expires_in=3600*24, leeway=10)
920920
token = mycwt.encode({"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, key)
921921
decoded = mycwt.decode(token, key)

cwt/cose_key.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,33 @@ def new(params: Dict[int, Any]) -> COSEKeyInterface:
7676
raise ValueError(f"Unsupported or unknown alg(3): {params[3]}.")
7777
raise ValueError(f"Unsupported or unknown kty(1): {params[1]}.")
7878

79+
@classmethod
80+
def generate_symmetric_key(
81+
cls,
82+
alg: Union[int, str] = "",
83+
kid: Union[bytes, str] = b"",
84+
key_ops: Optional[Union[List[int], List[str]]] = None,
85+
) -> COSEKeyInterface:
86+
"""
87+
Generates a symmetric COSE key from from a randomly genarated byte string.
88+
89+
Args:
90+
alg (Union[int, str]): An algorithm label(int) or name(str).
91+
Supported ``alg`` are listed in
92+
`Supported COSE Algorithms <https://python-cwt.readthedocs.io/en/stable/algorithms.html>`_.
93+
kid (Union[bytes, str]): A key identifier.
94+
key_ops (Union[List[int], List[str]]): A list of key operation values.
95+
Following values can be used:
96+
``1("sign")``, ``2("verify")``, ``3("encrypt")``, ``4("decrypt")``, ``5("wrap key")``,
97+
``6("unwrap key")``, ``7("derive key")``, ``8("derive bits")``,
98+
``9("MAC create")``, ``10("MAC verify")``
99+
Returns:
100+
COSEKeyInterface: A COSE key object.
101+
Raises:
102+
ValueError: Invalid arguments.
103+
"""
104+
return cls.from_symmetric_key(b"", alg, kid, key_ops)
105+
79106
@classmethod
80107
def from_symmetric_key(
81108
cls,

docs/cose_usage.rst

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ The following is a simple sample code using COSE API:
88
99
>>> from cwt import COSE, COSEKey
1010
>>> ctx = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True)
11-
>>> mac_key = COSEKey.from_symmetric_key(alg="HS256", kid="01")
11+
>>> mac_key = COSEKey.generate_symmetric_key(alg="HS256", kid="01")
1212
>>> encoded = ctx.encode_and_mac(b"Hello world!", mac_key)
1313
>>> encoded.hex()
1414
'd18443a10105a1044230314c48656c6c6f20776f726c642158205d0b144add282ccaac32a02e0d5eec76928ccadf3623271eb48e9464e2ee03b2'
@@ -29,7 +29,7 @@ Create a COSE MAC0 message, verify and decode it as follows:
2929
3030
from cwt import COSE, COSEKey
3131
32-
mac_key = COSEKey.from_symmetric_key(alg="HS256", kid="01")
32+
mac_key = COSEKey.generate_symmetric_key(alg="HS256", kid="01")
3333
ctx = COSE.new(alg_auto_inclusion=True, kid_auto_inclusion=True)
3434
encoded = ctx.encode_and_mac(b"Hello world!", mac_key)
3535
assert b"Hello world!" == ctx.decode(encoded, mac_key)
@@ -42,7 +42,7 @@ Following two samples are other ways of writing the above example:
4242
4343
from cwt import COSE, COSEKey
4444
45-
mac_key = COSEKey.from_symmetric_key(alg="HS256", kid="01")
45+
mac_key = COSEKey.generate_symmetric_key(alg="HS256", kid="01")
4646
ctx = COSE.new()
4747
encoded = ctx.encode_and_mac(
4848
b"Hello world!",
@@ -56,7 +56,7 @@ Following two samples are other ways of writing the above example:
5656
5757
from cwt import COSE, COSEKey
5858
59-
mac_key = COSEKey.from_symmetric_key(alg="HS256", kid="01")
59+
mac_key = COSEKey.generate_symmetric_key(alg="HS256", kid="01")
6060
ctx = COSE.new()
6161
encoded = ctx.encode_and_mac(
6262
b"Hello world!",
@@ -81,7 +81,7 @@ key distribution method.
8181
from cwt import COSE, COSEKey, Recipient
8282
8383
# The sender makes a COSE MAC message as follows:
84-
mac_key = COSEKey.from_symmetric_key(alg="HS512", kid="01")
84+
mac_key = COSEKey.generate_symmetric_key(alg="HS512", kid="01")
8585
r = Recipient.from_jwk({"alg": "direct"})
8686
r.apply(mac_key)
8787
ctx = COSE.new()
@@ -98,7 +98,7 @@ Following samples are other ways of writing the above sample:
9898
9999
# The sender side:
100100
# In contrast to from_jwk(), new() is low-level constructor.
101-
mac_key = COSEKey.from_symmetric_key(alg="HS512", kid="01")
101+
mac_key = COSEKey.generate_symmetric_key(alg="HS512", kid="01")
102102
r = Recipient.new(unprotected={"alg": "direct"})
103103
r.apply(mac_key)
104104
ctx = COSE.new()
@@ -113,7 +113,7 @@ Following samples are other ways of writing the above sample:
113113
114114
# The sender side:
115115
# new() can accept following raw COSE header parameters.
116-
mac_key = COSEKey.from_symmetric_key(alg="HS512", kid="01")
116+
mac_key = COSEKey.generate_symmetric_key(alg="HS512", kid="01")
117117
r = Recipient.new(unprotected={1: 7})
118118
r.apply(mac_key)
119119
ctx = COSE.new()
@@ -161,7 +161,7 @@ The AES key wrap algorithm can be used to wrap a MAC key as follows:
161161
from cwt import COSE, COSEKey, Recipient
162162
163163
# The sender side:
164-
mac_key = COSEKey.from_symmetric_key(alg="HS512")
164+
mac_key = COSEKey.generate_symmetric_key(alg="HS512")
165165
r = Recipient.from_jwk(
166166
{
167167
"kid": "01",
@@ -337,7 +337,7 @@ Key Agreement with Key Wrap
337337
from cwt import COSE, COSEKey, Recipient
338338
339339
# The sender side:
340-
mac_key = COSEKey.from_symmetric_key(alg="HS256")
340+
mac_key = COSEKey.generate_symmetric_key(alg="HS256")
341341
r = Recipient.from_jwk(
342342
{
343343
"kty": "EC",
@@ -389,7 +389,7 @@ Create a COSE Encrypt0 message, verify and decode it as follows:
389389
390390
from cwt import COSE, COSEKey
391391
392-
enc_key = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305", kid="01")
392+
enc_key = COSEKey.generate_symmetric_key(alg="ChaCha20/Poly1305", kid="01")
393393
394394
# The sender side:
395395
nonce = enc_key.generate_nonce()
@@ -407,7 +407,7 @@ Following two samples are other ways of writing the above example:
407407
408408
from cwt import COSE, COSEKey
409409
410-
enc_key = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305", kid="01")
410+
enc_key = COSEKey.generate_symmetric_key(alg="ChaCha20/Poly1305", kid="01")
411411
412412
# The sender side:
413413
nonce = enc_key.generate_nonce()
@@ -427,7 +427,7 @@ Following two samples are other ways of writing the above example:
427427
428428
from cwt import COSE, COSEKey
429429
430-
enc_key = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305", kid="01")
430+
enc_key = COSEKey.generate_symmetric_key(alg="ChaCha20/Poly1305", kid="01")
431431
432432
# The sender side:
433433
nonce = enc_key.generate_nonce()
@@ -457,7 +457,7 @@ key distribution method.
457457
458458
from cwt import COSE, COSEKey, Recipient
459459
460-
enc_key = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305", kid="01")
460+
enc_key = COSEKey.generate_symmetric_key(alg="ChaCha20/Poly1305", kid="01")
461461
462462
# The sender side:
463463
nonce = enc_key.generate_nonce()
@@ -519,7 +519,7 @@ The AES key wrap algorithm can be used to wrap an encryption key as follows:
519519
"k": "hJtXIZ2uSN5kbQfbtTNWbg", # A shared wrapping key
520520
},
521521
)
522-
enc_key = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305")
522+
enc_key = COSEKey.generate_symmetric_key(alg="ChaCha20/Poly1305")
523523
r.apply(enc_key)
524524
ctx = COSE.new(alg_auto_inclusion=True)
525525
encoded = ctx.encode_and_encrypt(b"Hello world!", key=enc_key, recipients=[r])
@@ -688,7 +688,7 @@ Key Agreement with Key Wrap
688688
from cwt import COSE, COSEKey, Recipient
689689
690690
# The sender side:
691-
enc_key = COSEKey.from_symmetric_key(alg="A128GCM")
691+
enc_key = COSEKey.generate_symmetric_key(alg="A128GCM")
692692
nonce = enc_key.generate_nonce()
693693
r = Recipient.from_jwk(
694694
{

docs/cwt_usage.rst

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ The following is a simple sample code using CWT API:
77
88
>>> import cwt
99
>>> from cwt import Claims, COSEKey
10-
>>> key = COSEKey.from_symmetric_key(alg="HS256", kid="01")
10+
>>> key = COSEKey.generate_symmetric_key(alg="HS256", kid="01")
1111
>>> token = cwt.encode({"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, key)
1212
>>> token.hex()
1313
'd18443a10105a05835a60172636f6170733a2f2f61732e6578616d706c65026764616a69616a690743313233041a609097b7051a609089a7061a609089a758201fad9b0a76803194bd11ca9b9b3cbbf1028005e15321665a768994f38c7127f7'
@@ -30,7 +30,7 @@ Create a MACed CWT, verify and decode it as follows:
3030
from cwt import COSEKey
3131
3232
try:
33-
key = COSEKey.from_symmetric_key(alg="HS256", kid="01")
33+
key = COSEKey.generate_symmetric_key(alg="HS256", kid="01")
3434
token = cwt.encode(
3535
{"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"},
3636
key,
@@ -63,7 +63,7 @@ A raw CWT structure (Dict[int, Any]) can also be used as follows:
6363
import cwt
6464
from cwt import COSEKey
6565
66-
key = COSEKey.from_symmetric_key(alg="HS256", kid="01")
66+
key = COSEKey.generate_symmetric_key(alg="HS256", kid="01")
6767
token = cwt.encode({1: "coaps://as.example", 2: "dajiaji", 7: b"123"}, key)
6868
decoded = cwt.decode(token, key)
6969
@@ -168,7 +168,7 @@ and decrypt it as follows:
168168
import cwt
169169
from cwt import COSEKey
170170
171-
enc_key = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305", kid="01")
171+
enc_key = COSEKey.generate_symmetric_key(alg="ChaCha20/Poly1305", kid="01")
172172
token = cwt.encode(
173173
{"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, enc_key
174174
)
@@ -182,7 +182,7 @@ Algorithms other than ``ChaCha20/Poly1305`` are also supported. The following is
182182
import cwt
183183
from cwt import COSEKey
184184
185-
enc_key = COSEKey.from_symmetric_key(alg="AES-CCM-16-64-256", kid="01")
185+
enc_key = COSEKey.generate_symmetric_key(alg="AES-CCM-16-64-256", kid="01")
186186
token = cwt.encode(
187187
{"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, enc_key
188188
)
@@ -201,7 +201,7 @@ Create a signed CWT and encrypt it, and then decrypt and verify the nested CWT a
201201
from cwt import COSEKey
202202
203203
# A shared encryption key.
204-
enc_key = COSEKey.from_symmetric_key(alg="ChaCha20/Poly1305", kid="enc-01")
204+
enc_key = COSEKey.generate_symmetric_key(alg="ChaCha20/Poly1305", kid="enc-01")
205205
206206
# Creates a CWT with ES256 signing.
207207
with open("./private_key.pem") as key_file:
@@ -233,7 +233,7 @@ If you want to change the settings, you can create your own ``CWT`` class instan
233233
234234
from cwt import COSEKey, CWT
235235
236-
key = COSEKey.from_symmetric_key(alg="HS256", kid="01")
236+
key = COSEKey.generate_symmetric_key(alg="HS256", kid="01")
237237
mycwt = CWT.new(expires_in=3600 * 24, leeway=10)
238238
token = mycwt.encode({"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}, key)
239239
decoded = mycwt.decode(token, key)

0 commit comments

Comments
 (0)