Skip to content

Commit d2cb342

Browse files
authored
Merge pull request #465 from kentakayama/fix-accept-zero-length-map-protected-header
Accept zero length map protected header
2 parents 97c0565 + 6643bd9 commit d2cb342

2 files changed

Lines changed: 23 additions & 6 deletions

File tree

cwt/cose.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -395,12 +395,17 @@ def decode_with_headers(
395395
p, u = self._decode_headers(data.value[0], data.value[1])
396396
alg = self._get_alg(p)
397397

398+
# Local variable `protected` is byte encoded protected header
399+
# Sender is allowed to encode empty protected header into a bstr-wrapped zero-length map << {} >> (0x40A0)
400+
# but Recipient MUST treat it as a zero-length byte string h'' (0x40) while decoding
401+
protected = data.value[0] if len(p) > 0 else b""
402+
398403
err: Exception = ValueError("key is not found.")
399404

400405
# Encrypt0
401406
if data.tag == 16:
402407
kid = self._get_kid(p, u)
403-
aad = self._dumps(["Encrypt0", data.value[0], external_aad])
408+
aad = self._dumps(["Encrypt0", protected, external_aad])
404409
nonce = u.get(5, None)
405410
if kid:
406411
for _, k in enumerate(keys):
@@ -435,7 +440,7 @@ def decode_with_headers(
435440
# MAC0
436441
if data.tag == 17:
437442
kid = self._get_kid(p, u)
438-
msg = self._dumps(["MAC0", data.value[0], external_aad, payload])
443+
msg = self._dumps(["MAC0", protected, external_aad, payload])
439444
if kid:
440445
for _, k in enumerate(keys):
441446
if k.kid != kid:
@@ -456,7 +461,7 @@ def decode_with_headers(
456461

457462
# MAC
458463
if data.tag == 97:
459-
to_be_maced = self._dumps(["MAC", data.value[0], external_aad, payload])
464+
to_be_maced = self._dumps(["MAC", protected, external_aad, payload])
460465
rs = Recipients.from_list(data.value[4], self._verify_kid, context)
461466
mac_auth_key = rs.derive_key(keys, alg, external_aad, "Mac_Recipient")
462467
mac_auth_key.verify(to_be_maced, data.value[3])
@@ -465,7 +470,7 @@ def decode_with_headers(
465470
# Signature1
466471
if data.tag == 18:
467472
kid = self._get_kid(p, u)
468-
to_be_signed = self._dumps(["Signature1", data.value[0], external_aad, payload])
473+
to_be_signed = self._dumps(["Signature1", protected, external_aad, payload])
469474
if kid:
470475
for _, k in enumerate(keys):
471476
if k.kid != kid:
@@ -510,7 +515,7 @@ def decode_with_headers(
510515
to_be_signed = self._dumps(
511516
[
512517
"Signature",
513-
data.value[0],
518+
protected,
514519
sig[0],
515520
external_aad,
516521
payload,
@@ -526,7 +531,7 @@ def decode_with_headers(
526531
to_be_signed = self._dumps(
527532
[
528533
"Signature",
529-
data.value[0],
534+
protected,
530535
sig[0],
531536
external_aad,
532537
payload,

tests/test_cose_sample_with_encode.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from secrets import token_bytes
22

33
import pytest
4+
from cbor2 import dumps, loads
45

56
from cwt import COSE, COSEAlgs, COSEHeaders, COSEKey, COSEMessage, Recipient, Signer
67

@@ -968,6 +969,17 @@ def test_cose_usage_examples_cose_signature1(self):
968969
)
969970
assert b"Hello world!" == recipient.decode(encoded3, pub_key)
970971

972+
# zero-length map protected header
973+
encoded4 = sender.encode(
974+
b"Hello world!",
975+
priv_key,
976+
unprotected={COSEHeaders.ALG: COSEAlgs.ES256, COSEHeaders.KID: b"01"},
977+
)
978+
loaded_encoded4 = loads(encoded4)
979+
loaded_encoded4.value[0] = bytes.fromhex("a0") # << {} >>
980+
encoded4 = dumps(loaded_encoded4)
981+
assert b"Hello world!" == recipient.decode(encoded4, pub_key)
982+
971983
def test_cose_usage_examples_cose_signature1_countersignature(self):
972984
# The sender side:
973985
priv_key = COSEKey.from_jwk(

0 commit comments

Comments
 (0)