2121from .recipient_interface import RecipientInterface
2222from .recipients import Recipients
2323from .signer import Signer
24- from .utils import to_cose_header
24+ from .utils import sort_keys_for_deterministic_encoding , to_cose_header
2525
2626
2727class COSE (CBORProcessor ):
@@ -36,6 +36,7 @@ def __init__(
3636 kid_auto_inclusion : bool = False ,
3737 verify_kid : bool = False ,
3838 ca_certs : str = "" ,
39+ deterministic_header : bool = False ,
3940 ):
4041 if not isinstance (alg_auto_inclusion , bool ):
4142 raise ValueError ("alg_auto_inclusion should be bool." )
@@ -58,13 +59,18 @@ def __init__(
5859 for _ , _ , der_bytes in pem .unarmor (f .read (), multiple = True ):
5960 self ._ca_certs .append (der_bytes )
6061
62+ if not isinstance (deterministic_header , bool ):
63+ raise ValueError ("deterministic_header should be bool." )
64+ self ._deterministic_header = deterministic_header
65+
6166 @classmethod
6267 def new (
6368 cls ,
6469 alg_auto_inclusion : bool = False ,
6570 kid_auto_inclusion : bool = False ,
6671 verify_kid : bool = False ,
6772 ca_certs : str = "" ,
73+ deterministic_header : bool = False ,
6874 ):
6975 """
7076 Constructor.
@@ -80,8 +86,10 @@ def new(
8086 of trusted root certificates. You should specify private CA
8187 certificates in your target system. There should be no need to
8288 use the public CA certificates for the Web PKI.
89+ deterministic_header(bool): The indicator whether the protected and unprotected
90+ headers will be deterministically encoded defined in section 4.2.1 of RFC 8949.
8391 """
84- return cls (alg_auto_inclusion , kid_auto_inclusion , verify_kid , ca_certs )
92+ return cls (alg_auto_inclusion , kid_auto_inclusion , verify_kid , ca_certs , deterministic_header )
8593
8694 @property
8795 def alg_auto_inclusion (self ) -> bool :
@@ -561,6 +569,11 @@ def _encode_headers(
561569 if self ._kid_auto_inclusion and key .kid :
562570 u [4 ] = key .kid
563571
572+ # sort the key for deterministic encoding
573+ if self ._deterministic_header :
574+ p = sort_keys_for_deterministic_encoding (p )
575+ u = sort_keys_for_deterministic_encoding (u )
576+
564577 # Check the protected header is empty if the algorithm is non AEAD (AES-CBC or AES-CTR)
565578 # because section 4 of RFC9459 says "The 'protected' header MUST be a zero-length byte string."
566579 alg = p [1 ] if 1 in p else u .get (1 , 0 )
0 commit comments