Skip to content

Commit

Permalink
Merge pull request #138 from dajiaji/add-raw-key
Browse files Browse the repository at this point in the history
Add raw key.
  • Loading branch information
dajiaji authored Jun 24, 2021
2 parents f7465a4 + 6e2ba85 commit 7f06449
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 18 deletions.
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Changes
Unreleased
----------

- Add RawKey for key material. `#138 <https://github.com/dajiaji/python-cwt/pull/138>`__
- Make MAC key can be used for KDF. `#137 <https://github.com/dajiaji/python-cwt/pull/137>`__
- Remove COSEKeyInterface from RecipientInterface. `#137 <https://github.com/dajiaji/python-cwt/pull/137>`__
- Implement AESKeyWrap which has COSEKeyInterface. `#137 <https://github.com/dajiaji/python-cwt/pull/137>`__
- Add encode_key() to RecipientInterface. `#134 <https://github.com/dajiaji/python-cwt/pull/134>`__
Expand Down
31 changes: 31 additions & 0 deletions cwt/algs/raw.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from typing import Any, Dict

from ..cose_key_interface import COSEKeyInterface


class RawKey(COSEKeyInterface):
def __init__(self, params: Dict[int, Any]):
super().__init__(params)

self._key: bytes = b""
self._alg = None

# Validate kty.
if params[1] != 4:
raise ValueError("kty(1) should be Symmetric(4).")

# Validate k.
if -1 not in params:
raise ValueError("k(-1) should be set.")
if not isinstance(params[-1], bytes):
raise ValueError("k(-1) should be bytes(bstr).")
self._key = params[-1]

@property
def key(self) -> bytes:
return self._key

def to_dict(self) -> Dict[int, Any]:
res = super().to_dict()
res[-1] = self._key
return res
5 changes: 4 additions & 1 deletion cwt/cose_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

from .algs.ec2 import EC2Key
from .algs.okp import OKPKey
from .algs.raw import RawKey
from .algs.rsa import RSAKey
from .algs.symmetric import AESCCMKey, AESGCMKey, AESKeyWrap, ChaCha20Key, HMACKey
from .const import (
Expand Down Expand Up @@ -80,7 +81,7 @@ def new(params: Dict[int, Any]) -> COSEKeyInterface:
def from_symmetric_key(
cls,
key: Union[bytes, str] = b"",
alg: Union[int, str] = "HMAC 256/256",
alg: Union[int, str] = "",
kid: Union[bytes, str] = b"",
key_ops: Optional[Union[List[int], List[str]]] = None,
) -> COSEKeyInterface:
Expand All @@ -103,6 +104,8 @@ def from_symmetric_key(
"""
if isinstance(key, str):
key = key.encode("utf-8")
if alg == "":
return RawKey({1: 4, -1: key})
alg_id = alg if isinstance(alg, int) else COSE_ALGORITHMS_SYMMETRIC.get(alg, 0)
if alg_id == 0:
raise ValueError(f"Unsupported or unknown alg(3): {alg}.")
Expand Down
58 changes: 58 additions & 0 deletions tests/test_algs_raw.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"""
Tests for RawKey.
"""
import pytest

from cwt.algs.raw import RawKey


class TestRawKey:
"""
Tests for RawKey.
"""

def test_raw_key_constructor(self):
key = RawKey(
{
1: 4,
-1: b"mysecret",
}
)
assert key.key == b"mysecret"
assert key.alg is None
assert key.key_ops == []
assert key.base_iv is None

@pytest.mark.parametrize(
"invalid, msg",
[
(
{1: 2},
"kty(1) should be Symmetric(4).",
),
(
{1: 4},
"k(-1) should be set.",
),
(
{1: 4, -1: 123},
"k(-1) should be bytes(bstr).",
),
],
)
def test_symmetric_key_constructor_with_invalid_args(self, invalid, msg):
with pytest.raises(ValueError) as err:
RawKey(invalid)
pytest.fail("SymmetricKey should fail.")
assert msg in str(err.value)

def test_raw_key_to_dict(self):
key = RawKey(
{
1: 4,
-1: b"mysecret",
}
)
k = key.to_dict()
assert k[1] == 4
assert k[-1] == b"mysecret"
2 changes: 1 addition & 1 deletion tests/test_cose_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def test_key_builder_from_symmetric_key_with_invalid_alg(self, alg):
)
def test_key_builder_from_symmetric_key_with_invalid_key_ops(self, key_ops):
with pytest.raises(ValueError) as err:
COSEKey.from_symmetric_key("mysecret", key_ops=key_ops)
COSEKey.from_symmetric_key("mysecret", alg="HS256", key_ops=key_ops)
pytest.fail("from_symmetric_key should fail.")
assert "Unsupported or unknown key_ops." in str(err.value)

Expand Down
8 changes: 2 additions & 6 deletions tests/test_cose_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,7 @@ def test_cose_usage_examples_cose_mac_direct_hkdf_sha_256(self):
},
)
shared_material = token_bytes(32)
shared_key = COSEKey.from_symmetric_key(
shared_material, alg="A256GCM", kid="01"
)
shared_key = COSEKey.from_symmetric_key(shared_material, kid="01")
mac_key = recipient.apply(shared_key, context={"alg": "HS256"})
ctx = COSE.new(alg_auto_inclusion=True)
encoded = ctx.encode_and_mac(
Expand Down Expand Up @@ -181,9 +179,7 @@ def test_cose_usage_examples_cose_encrypt_direct_hkdf_sha_256(self):
},
)
shared_material = token_bytes(32)
shared_key = COSEKey.from_symmetric_key(
shared_material, alg="A256GCM", kid="01"
)
shared_key = COSEKey.from_symmetric_key(shared_material, kid="01")
enc_key = recipient.apply(shared_key, context={"alg": "A256GCM"})
ctx = COSE.new(alg_auto_inclusion=True)
encoded = ctx.encode_and_encrypt(
Expand Down
12 changes: 6 additions & 6 deletions tests/test_cwt.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def test_cwt_encode_with_invalid_key(self, ctx, invalid_key):
assert "The key operation could not be specified." in str(err.value)

def test_cwt_encode_and_mac_with_default_alg(self, ctx):
key = COSEKey.from_symmetric_key("mysecret")
key = COSEKey.from_symmetric_key("mysecret", alg="HS256")
token = ctx.encode_and_mac(
{1: "https://as.example", 2: "someone", 7: b"123"}, key
)
Expand Down Expand Up @@ -197,7 +197,7 @@ def test_cwt_encode_and_mac_with_empty_recipient(self, ctx):
],
)
def test_cwt_encode_and_mac_with_invalid_args(self, ctx, invalid):
key = COSEKey.from_symmetric_key("mysecret")
key = COSEKey.from_symmetric_key("mysecret", alg="HS256")
with pytest.raises(ValueError) as err:
ctx.encode_and_mac(invalid, key)
pytest.fail("encode_and_mac should fail.")
Expand All @@ -217,7 +217,7 @@ def test_cwt_encode_and_mac_with_invalid_args(self, ctx, invalid):
],
)
def test_cwt_encode_and_mac_with_invalid_claims(self, ctx, invalid, msg):
key = COSEKey.from_symmetric_key("mysecret")
key = COSEKey.from_symmetric_key("mysecret", alg="HS256")
with pytest.raises(ValueError) as err:
ctx.encode_and_mac(invalid, key)
pytest.fail("encode_and_mac should fail.")
Expand Down Expand Up @@ -494,11 +494,11 @@ def test_cwt_encode_and_sign_with_signatures_kid_mismatch(self, ctx):
assert "Verification key not found." in str(err.value)

def test_cwt_decode_with_invalid_mac_key(self, ctx):
key = COSEKey.from_symmetric_key("mysecret")
key = COSEKey.from_symmetric_key("mysecret", alg="HS256")
token = ctx.encode_and_mac(
{1: "https://as.example", 2: "someone", 7: b"123"}, key
)
wrong_key = COSEKey.from_symmetric_key("xxxxxxxxxx")
wrong_key = COSEKey.from_symmetric_key("xxxxxxxxxx", alg="HS256")
with pytest.raises(VerifyError) as err:
res = ctx.decode(token, wrong_key)
pytest.fail("decode should fail: res=%s" % vars(res))
Expand Down Expand Up @@ -552,7 +552,7 @@ def test_cwt_decode_with_invalid_enc_key(self, ctx):
],
)
def test_cwt_decode_with_invalid_claim(self, ctx, invalid, msg):
mac_key = COSEKey.from_symmetric_key("mysecret")
mac_key = COSEKey.from_symmetric_key("mysecret", alg="HS256")
token = ctx.encode_and_mac(invalid, mac_key)
with pytest.raises(VerifyError) as err:
ctx.decode(token, mac_key)
Expand Down
8 changes: 4 additions & 4 deletions tests/test_cwt_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class TestSample:
"""

def test_sample_readme_maced_cwt_with_json_dict_old(self):
key = COSEKey.from_symmetric_key("mysecretpassword")
key = COSEKey.from_symmetric_key("mysecretpassword", alg="HS256")
encoded = cwt.encode_and_mac(
Claims.from_json(
{"iss": "coaps://as.example", "sub": "dajiaji", "cti": "123"}
Expand All @@ -104,7 +104,7 @@ def test_sample_readme_maced_cwt_with_json_dict(self):
assert 1 in decoded and decoded[1] == "coaps://as.example"

def test_sample_readme_maced_cwt_with_json_str_old(self):
key = COSEKey.from_symmetric_key("mysecretpassword")
key = COSEKey.from_symmetric_key("mysecretpassword", alg="HS256")
encoded = cwt.encode_and_mac(
Claims.from_json(
'{"iss":"coaps://as.example","sub":"dajiaji","cti":"123"}'
Expand All @@ -123,7 +123,7 @@ def test_sample_readme_maced_cwt_with_json_str(self):
assert 1 in decoded and decoded[1] == "coaps://as.example"

def test_sample_readme_maced_cwt_with_json_bytes_old(self):
key = COSEKey.from_symmetric_key("mysecretpassword")
key = COSEKey.from_symmetric_key("mysecretpassword", alg="HS256")
encoded = cwt.encode_and_mac(
Claims.from_json(
b'{"iss":"coaps://as.example","sub":"dajiaji","cti":"123"}'
Expand All @@ -142,7 +142,7 @@ def test_sample_readme_maced_cwt_with_json_bytes(self):
assert 1 in decoded and decoded[1] == "coaps://as.example"

def test_sample_readme_maced_cwt_old(self):
key = COSEKey.from_symmetric_key("mysecretpassword")
key = COSEKey.from_symmetric_key("mysecretpassword", alg="HS256")
encoded = cwt.encode_and_mac(
{1: "coaps://as.example", 2: "dajiaji", 7: b"123"}, key
)
Expand Down

0 comments on commit 7f06449

Please sign in to comment.