55from datetime import datetime , timezone
66from cryptography .hazmat .primitives import serialization
77from cryptography .hazmat .primitives .asymmetric .ec import EllipticCurvePublicKey
8+ from cryptography .hazmat .primitives .asymmetric .ed25519 import Ed25519PublicKey
89from pycose .keys import CoseKey , EC2Key
910from typing import Union
1011
@@ -23,13 +24,13 @@ class MdocCborIssuer:
2324 """
2425 def __init__ (
2526 self ,
26- key_label : str = None ,
27- user_pin : str = None ,
28- lib_path : str = None ,
29- slot_id : int = None ,
27+ key_label : str | None = None ,
28+ user_pin : str | None = None ,
29+ lib_path : str | None = None ,
30+ slot_id : int | None = None ,
3031 hsm : bool = False ,
31- alg : str = None ,
32- kid : str = None ,
32+ alg : str | None = None ,
33+ kid : str | None = None ,
3334 private_key : Union [dict , CoseKey ] = {},
3435 cert_info : dict | None = None ,
3536 ):
@@ -74,11 +75,11 @@ def new(
7475 self ,
7576 data : dict ,
7677 doctype : str ,
77- validity : dict = None ,
78- devicekeyinfo : Union [ dict , CoseKey , str ] = None ,
79- cert_path : str = None ,
80- revocation : dict = None ,
81- status : dict = None
78+ validity : dict | None = None ,
79+ devicekeyinfo : dict | CoseKey | str | None = None ,
80+ cert_path : str | None = None ,
81+ revocation : dict | None = None ,
82+ status : dict | None = None
8283 ) -> dict :
8384 """
8485 create a new mdoc with signed mso
@@ -95,49 +96,66 @@ def new(
9596 """
9697 if isinstance (devicekeyinfo , dict ):
9798 devicekeyinfoCoseKeyObject = CoseKey .from_dict (devicekeyinfo )
98- devicekeyinfo = {
99- 1 : devicekeyinfoCoseKeyObject .kty .identifier ,
100- - 1 : devicekeyinfoCoseKeyObject .crv .identifier ,
101- - 2 : devicekeyinfoCoseKeyObject .x ,
102- - 3 : devicekeyinfoCoseKeyObject .y ,
103- }
99+ if devicekeyinfoCoseKeyObject .kty .identifier == 2 : # EC2Key
100+ devicekeyinfo = {
101+ 1 : devicekeyinfoCoseKeyObject .kty .identifier ,
102+ - 1 : devicekeyinfoCoseKeyObject .crv .identifier ,
103+ - 2 : devicekeyinfoCoseKeyObject .x ,
104+ - 3 : devicekeyinfoCoseKeyObject .y ,
105+ }
106+ elif devicekeyinfoCoseKeyObject .kty .identifier == 1 : # OKPKey
107+ devicekeyinfo = {
108+ 1 : devicekeyinfoCoseKeyObject .kty .identifier ,
109+ - 1 : devicekeyinfoCoseKeyObject .crv .identifier ,
110+ - 2 : devicekeyinfoCoseKeyObject .x ,
111+ }
104112 if isinstance (devicekeyinfo , str ):
105113 device_key_bytes = base64 .urlsafe_b64decode (devicekeyinfo .encode ("utf-8" ))
106- public_key :EllipticCurvePublicKey = serialization .load_pem_public_key (device_key_bytes )
107- curve_name = public_key .curve .name
108- curve_map = {
109- "secp256r1" : 1 , # NIST P-256
110- "secp384r1" : 2 , # NIST P-384
111- "secp521r1" : 3 , # NIST P-521
112- "brainpoolP256r1" : 8 , # Brainpool P-256
113- "brainpoolP384r1" : 9 , # Brainpool P-384
114- "brainpoolP512r1" : 10 , # Brainpool P-512
115- # Add more curve mappings as needed
116- }
117- curve_identifier = curve_map .get (curve_name )
118-
119- # Extract the x and y coordinates from the public key
120- x = public_key .public_numbers ().x .to_bytes (
121- (public_key .public_numbers ().x .bit_length () + 7 )
122- // 8 , # Number of bytes needed
123- "big" , # Byte order
124- )
125-
126- y = public_key .public_numbers ().y .to_bytes (
127- (public_key .public_numbers ().y .bit_length () + 7 )
128- // 8 , # Number of bytes needed
129- "big" , # Byte order
130- )
131-
132- devicekeyinfo = {
133- 1 : 2 ,
134- - 1 : curve_identifier ,
135- - 2 : x ,
136- - 3 : y ,
137- }
138-
139- else :
140- devicekeyinfo : CoseKey = devicekeyinfo
114+ public_key = serialization .load_pem_public_key (device_key_bytes )
115+
116+ if isinstance (public_key , EllipticCurvePublicKey ):
117+ curve_name = public_key .curve .name
118+ curve_map = {
119+ "secp256r1" : 1 , # NIST P-256
120+ "secp384r1" : 2 , # NIST P-384
121+ "secp521r1" : 3 , # NIST P-521
122+ "brainpoolP256r1" : 8 , # Brainpool P-256
123+ "brainpoolP384r1" : 9 , # Brainpool P-384
124+ "brainpoolP512r1" : 10 , # Brainpool P-512
125+ # Add more curve mappings as needed
126+ }
127+ curve_identifier = curve_map .get (curve_name )
128+
129+ # Extract the x and y coordinates from the public key
130+ x = public_key .public_numbers ().x .to_bytes (
131+ (public_key .public_numbers ().x .bit_length () + 7 )
132+ // 8 , # Number of bytes needed
133+ "big" , # Byte order
134+ )
135+
136+ y = public_key .public_numbers ().y .to_bytes (
137+ (public_key .public_numbers ().y .bit_length () + 7 )
138+ // 8 , # Number of bytes needed
139+ "big" , # Byte order
140+ )
141+
142+ devicekeyinfo = {
143+ 1 : 2 ,
144+ - 1 : curve_identifier ,
145+ - 2 : x ,
146+ - 3 : y ,
147+ }
148+ elif isinstance (public_key , Ed25519PublicKey ):
149+ devicekeyinfo = {
150+ 1 : 1 , # OKPKey
151+ - 1 : "Ed25519" , # Curve identifier for Ed25519
152+ - 2 : public_key .public_bytes (
153+ encoding = serialization .Encoding .Raw ,
154+ format = serialization .PublicFormat .Raw
155+ )
156+ }
157+ else :
158+ raise TypeError ("Loaded public key is not an EllipticCurvePublicKey" )
141159
142160 if self .hsm :
143161 msoi = MsoIssuer (
@@ -166,7 +184,7 @@ def new(
166184 cert_info = self .cert_info
167185 )
168186
169- mso = msoi .sign (doctype = doctype , device_key = devicekeyinfo ,valid_from = datetime .now (timezone .utc ))
187+ mso = msoi .sign (doctype = doctype , device_key = devicekeyinfo , valid_from = datetime .now (timezone .utc ))
170188
171189 mso_cbor = mso .encode (
172190 tag = False ,
0 commit comments