1717from cryptography .hazmat .primitives .asymmetric import ec
1818from cryptography .hazmat .primitives import hashes
1919from cryptography .hazmat .primitives .asymmetric .utils import decode_dss_signature
20+
21+ # eddsa25519ph is not supported by cryptography, so we need to use pycryptodome
22+ from Crypto .PublicKey import ECC
23+ from Crypto .Signature import eddsa
24+ from Crypto .Hash import SHA512
2025import math
2126
2227from suit_generator .suit_kms_base import SuitKMSBase
@@ -87,7 +92,7 @@ def _verify_signing_key_type(self, private_key, algorithm: str) -> bool:
8792 if isinstance (private_key , EllipticCurvePrivateKey ):
8893 return f"es-{ private_key .key_size } " == algorithm
8994 elif isinstance (private_key , Ed25519PrivateKey ) or isinstance (private_key , Ed448PrivateKey ):
90- return "eddsa" == algorithm
95+ return "eddsa" == algorithm or "hash-eddsa" == algorithm
9196 else :
9297 raise ValueError (f"Key { type (private_key )} not supported" )
9398
@@ -104,11 +109,19 @@ def _create_cose_ed_signature(self, input_data, private_key) -> bytes:
104109 """Create ECDSA signature and return signature bytes."""
105110 return private_key .sign (input_data )
106111
107- def _get_sign_method (self , private_key ) -> bool :
112+ def _create_cose_ed_prehashed_signature (self , input_data , private_key ) -> bytes :
113+ prehashed_message = SHA512 .new (input_data )
114+ key = ECC .import_key (private_key )
115+ signer = eddsa .new (key , "rfc8032" )
116+ return signer .sign (prehashed_message )
117+
118+ def _get_sign_method (self , private_key , algorithm ) -> bool :
108119 """Return sign method based on key type."""
109120 if isinstance (private_key , EllipticCurvePrivateKey ):
110121 return self ._create_cose_es_signature
111122 elif isinstance (private_key , Ed25519PrivateKey ) or isinstance (private_key , Ed448PrivateKey ):
123+ if algorithm == "hash-eddsa" :
124+ return self ._create_cose_ed_prehashed_signature
112125 return self ._create_cose_ed_signature
113126 else :
114127 raise ValueError (f"Key { type (private_key )} not supported" )
@@ -146,7 +159,13 @@ def sign(self, data: bytes, key_name: str, algorithm: str, context: str) -> byte
146159 if not self ._verify_signing_key_type (private_key , algorithm ):
147160 raise ValueError (f"Key { key_file_name } is not compatible with algorithm { algorithm } " )
148161
149- sign_method = self ._get_sign_method (private_key )
162+ sign_method = self ._get_sign_method (private_key , algorithm )
163+
164+ if algorithm == "hash-eddsa" :
165+ # In the special case of hash-eddsa, we need to use pycryptodome, which needs the raw key
166+ # data to import the key
167+ private_key = open (private_key_path ).read ()
168+
150169 signature = sign_method (data , private_key )
151170
152171 return signature
0 commit comments