2525import os
2626from signxml .algorithms import SignatureMethod
2727from cryptography .hazmat .primitives import serialization
28+ from cryptography .hazmat .primitives .asymmetric import rsa , dsa , ec , ed25519 , ed448
2829
2930from openleadr import utils
3031from .preflight import preflight_message
@@ -64,26 +65,53 @@ def parse_message(data):
6465 return message_type , message_payload
6566
6667
67- def get_signature_algorithm (key_data , default_algorithm = "rsa-sha256" ):
68+ def load_private_key (key_data ):
6869 """
69- Derive the signature algorithm based on the key type. Accepted key types are EC, DSA and RSA keys.
70- Returns a string that can be used to lookup a signature algorithm by fragment.
71- If key is not EC or DSA, the lookup will return rsa-sha256, which is the default signature algorithm
72- for XMLSigner objects.
70+ Load the key based on key data. .pem and .der keys can be loaded.
71+ Returns a private key object.
7372 """
73+ with open (key_data , "rb" ) as f :
74+ key_data = f .read ()
7475 try :
7576 key = serialization .load_pem_private_key (key_data , password = None )
7677 except ValueError :
7778 try :
7879 key = serialization .load_der_private_key (key_data , password = None )
7980 except ValueError :
80- logger .warning (f"Could not load key: unknown key type." )
81- key_type = str (type (key )).lower ()
82- if "ec" in key_type and hasattr (key , "curve" ):
83- return "ecdsa-sha3-256"
84- elif "dsa" in key_type :
81+ logger .warning (f"Could not load key: unknown key file format." )
82+ return key
83+
84+ def get_private_key_type (key ):
85+ """
86+ Determine the type of the key. ED25519 and ED448 are not supported by SignXML so these are rejected.
87+ """
88+ if isinstance (key , rsa .RSAPrivateKey ):
89+ return "rsa"
90+ elif isinstance (key , dsa .DSAPrivateKey ):
91+ return "dsa"
92+ elif isinstance (key , ec .EllipticCurvePrivateKey ):
93+ return "ec"
94+ elif isinstance (key , ed25519 .Ed25519PrivateKey ):
95+ logger .warning ("ED25519 keys are not supported" )
96+ elif isinstance (key , ed448 .Ed448PrivateKey ):
97+ logger .warning ("ED448 keys are not supported" )
98+ logger .warning ("Unknown key type." )
99+
100+
101+ def get_signature_algorithm_from_private_key (key_data , default_algorithm = "rsa-sha256" ):
102+ """
103+ Derive a signature algorithm based on the private key type. Accepted key types are EC, DSA and RSA keys.
104+ Returns a string that can be used to lookup a signature algorithm by fragment.
105+ By default the lookup will return rsa-sha256, which is the default signature algorithm for XMLSigner objects.
106+ """
107+ key = load_private_key (key_data )
108+ key_type = get_private_key_type (key )
109+ if key_type == "rsa" :
110+ return "rsa-sha256"
111+ elif key_type == "dsa" :
85112 return "dsa-sha256"
86-
113+ elif key_type == "ec" :
114+ return "ecdsa-sha3-256"
87115 return default_algorithm
88116
89117def create_message (message_type , cert = None , key = None , passphrase = None , disable_signature = False , ** message_payload ):
@@ -96,7 +124,7 @@ def create_message(message_type, cert=None, key=None, passphrase=None, disable_s
96124 envelope = TEMPLATES .get_template ('oadrPayload.xml' )
97125 if cert and key and not disable_signature :
98126 tree = etree .fromstring (signed_object )
99- SIGNER .sign_alg = SignatureMethod .from_fragment (get_signature_algorithm (key ))
127+ SIGNER .sign_alg = SignatureMethod .from_fragment (get_signature_algorithm_from_private_key (key ))
100128 signature_tree = SIGNER .sign (tree ,
101129 key = key ,
102130 cert = cert ,
0 commit comments