Skip to content

Commit 15ba26f

Browse files
committed
Merge branch 'main' into fix-generate-zero-length-protected-header-for-non-aead
2 parents affdfc7 + d2cb342 commit 15ba26f

3 files changed

Lines changed: 25 additions & 8 deletions

File tree

cwt/cose.py

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

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

401406
# Encrypt0
402407
if data.tag == 16:
403408
kid = self._get_kid(p, u)
404-
aad = self._dumps(["Encrypt0", data.value[0], external_aad])
409+
aad = self._dumps(["Encrypt0", protected, external_aad])
405410
nonce = u.get(5, None)
406411
if kid:
407412
for _, k in enumerate(keys):
@@ -436,7 +441,7 @@ def decode_with_headers(
436441
# MAC0
437442
if data.tag == 17:
438443
kid = self._get_kid(p, u)
439-
msg = self._dumps(["MAC0", data.value[0], external_aad, payload])
444+
msg = self._dumps(["MAC0", protected, external_aad, payload])
440445
if kid:
441446
for _, k in enumerate(keys):
442447
if k.kid != kid:
@@ -457,7 +462,7 @@ def decode_with_headers(
457462

458463
# MAC
459464
if data.tag == 97:
460-
to_be_maced = self._dumps(["MAC", data.value[0], external_aad, payload])
465+
to_be_maced = self._dumps(["MAC", protected, external_aad, payload])
461466
rs = Recipients.from_list(data.value[4], self._verify_kid, context)
462467
mac_auth_key = rs.derive_key(keys, alg, external_aad, "Mac_Recipient")
463468
mac_auth_key.verify(to_be_maced, data.value[3])
@@ -466,7 +471,7 @@ def decode_with_headers(
466471
# Signature1
467472
if data.tag == 18:
468473
kid = self._get_kid(p, u)
469-
to_be_signed = self._dumps(["Signature1", data.value[0], external_aad, payload])
474+
to_be_signed = self._dumps(["Signature1", protected, external_aad, payload])
470475
if kid:
471476
for _, k in enumerate(keys):
472477
if k.kid != kid:
@@ -511,7 +516,7 @@ def decode_with_headers(
511516
to_be_signed = self._dumps(
512517
[
513518
"Signature",
514-
data.value[0],
519+
protected,
515520
sig[0],
516521
external_aad,
517522
payload,
@@ -527,7 +532,7 @@ def decode_with_headers(
527532
to_be_signed = self._dumps(
528533
[
529534
"Signature",
530-
data.value[0],
535+
protected,
531536
sig[0],
532537
external_aad,
533538
payload,

tests/test_algs_symmetric.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,7 @@ def test_aesctr_key_decrypt_with_invalid_nonce(self):
877877
nonce = token_bytes(16)
878878
encrypted = key.encrypt(b"Hello world!", nonce=nonce)
879879
# alternate the nonce by incrementing the last byte
880-
invalid_nonce = nonce[0:-1] + (nonce[-1] + 1 % 256).to_bytes(1, "big")
880+
invalid_nonce = nonce[0:-1] + ((nonce[-1] + 1) % 256).to_bytes(1, "big")
881881
assert nonce != invalid_nonce
882882
decrypted = key.decrypt(encrypted, nonce=invalid_nonce)
883883
assert encrypted != decrypted
@@ -1035,7 +1035,7 @@ def test_aescbc_key_decrypt_with_invalid_nonce(self):
10351035
nonce = token_bytes(16)
10361036
encrypted = key.encrypt(b"Hello world!", nonce=nonce)
10371037
# alternate the nonce by incrementing the last byte
1038-
invalid_nonce = nonce[0:-1] + (nonce[-1] + 1 % 256).to_bytes(1, "big")
1038+
invalid_nonce = nonce[0:-1] + ((nonce[-1] + 1) % 256).to_bytes(1, "big")
10391039
assert nonce != invalid_nonce
10401040
decrypted = key.decrypt(encrypted, nonce=invalid_nonce)
10411041
assert encrypted != decrypted

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)