5
5
from datetime import datetime , timezone
6
6
from cryptography .hazmat .primitives import serialization
7
7
from cryptography .hazmat .primitives .asymmetric .ec import EllipticCurvePublicKey
8
+ from cryptography .hazmat .primitives .asymmetric .ed25519 import Ed25519PublicKey
9
+ from cryptography .hazmat .primitives .asymmetric .rsa import RSAPublicKey
8
10
from pycose .keys import CoseKey , EC2Key
9
11
from typing import Union
10
12
@@ -23,14 +25,15 @@ class MdocCborIssuer:
23
25
"""
24
26
def __init__ (
25
27
self ,
26
- key_label : str = None ,
27
- user_pin : str = None ,
28
- lib_path : str = None ,
29
- slot_id : int = None ,
28
+ key_label : str | None = None ,
29
+ user_pin : str | None = None ,
30
+ lib_path : str | None = None ,
31
+ slot_id : int | None = None ,
30
32
hsm : bool = False ,
31
- alg : str = None ,
32
- kid : str = None ,
33
+ alg : str | None = None ,
34
+ kid : str | None = None ,
33
35
private_key : Union [dict , CoseKey ] = {},
36
+ cert_info : dict | None = None ,
34
37
):
35
38
"""
36
39
Initialize a new MdocCborIssuer
@@ -67,16 +70,17 @@ def __init__(
67
70
self .hsm = hsm
68
71
self .alg = alg
69
72
self .kid = kid
73
+ self .cert_info = cert_info
70
74
71
75
def new (
72
76
self ,
73
77
data : dict ,
74
78
doctype : str ,
75
- validity : dict = None ,
76
- devicekeyinfo : Union [ dict , CoseKey , str ] = None ,
77
- cert_path : str = None ,
78
- revocation : dict = None ,
79
- status : dict = None
79
+ validity : dict | None = None ,
80
+ devicekeyinfo : dict | CoseKey | str | None = None ,
81
+ cert_path : str | None = None ,
82
+ revocation : dict | None = None ,
83
+ status : dict | None = None
80
84
) -> dict :
81
85
"""
82
86
create a new mdoc with signed mso
@@ -93,49 +97,86 @@ def new(
93
97
"""
94
98
if isinstance (devicekeyinfo , dict ):
95
99
devicekeyinfoCoseKeyObject = CoseKey .from_dict (devicekeyinfo )
96
- devicekeyinfo = {
97
- 1 : devicekeyinfoCoseKeyObject .kty .identifier ,
98
- - 1 : devicekeyinfoCoseKeyObject .crv .identifier ,
99
- - 2 : devicekeyinfoCoseKeyObject .x ,
100
- - 3 : devicekeyinfoCoseKeyObject .y ,
101
- }
100
+ if devicekeyinfoCoseKeyObject .kty .identifier == 2 : # EC2Key
101
+ devicekeyinfo = {
102
+ 1 : devicekeyinfoCoseKeyObject .kty .identifier ,
103
+ - 1 : devicekeyinfoCoseKeyObject .crv .identifier ,
104
+ - 2 : devicekeyinfoCoseKeyObject .x ,
105
+ - 3 : devicekeyinfoCoseKeyObject .y ,
106
+ }
107
+ elif devicekeyinfoCoseKeyObject .kty .identifier == 1 : # OKPKey
108
+ devicekeyinfo = {
109
+ 1 : devicekeyinfoCoseKeyObject .kty .identifier ,
110
+ - 1 : devicekeyinfoCoseKeyObject .crv .identifier ,
111
+ - 2 : devicekeyinfoCoseKeyObject .x ,
112
+ }
113
+ elif devicekeyinfoCoseKeyObject .kty .identifier == 3 : # RSAKey
114
+ devicekeyinfo = {
115
+ 1 : devicekeyinfoCoseKeyObject .kty .identifier ,
116
+ - 1 : devicekeyinfoCoseKeyObject .n ,
117
+ - 2 : devicekeyinfoCoseKeyObject .e ,
118
+ }
119
+ else :
120
+ raise TypeError ("Unsupported key type in devicekeyinfo" )
102
121
if isinstance (devicekeyinfo , str ):
103
122
device_key_bytes = base64 .urlsafe_b64decode (devicekeyinfo .encode ("utf-8" ))
104
- public_key :EllipticCurvePublicKey = serialization .load_pem_public_key (device_key_bytes )
105
- curve_name = public_key .curve .name
106
- curve_map = {
107
- "secp256r1" : 1 , # NIST P-256
108
- "secp384r1" : 2 , # NIST P-384
109
- "secp521r1" : 3 , # NIST P-521
110
- "brainpoolP256r1" : 8 , # Brainpool P-256
111
- "brainpoolP384r1" : 9 , # Brainpool P-384
112
- "brainpoolP512r1" : 10 , # Brainpool P-512
113
- # Add more curve mappings as needed
114
- }
115
- curve_identifier = curve_map .get (curve_name )
116
-
117
- # Extract the x and y coordinates from the public key
118
- x = public_key .public_numbers ().x .to_bytes (
119
- (public_key .public_numbers ().x .bit_length () + 7 )
120
- // 8 , # Number of bytes needed
121
- "big" , # Byte order
122
- )
123
+ public_key = serialization .load_pem_public_key (device_key_bytes )
124
+
125
+ if isinstance (public_key , EllipticCurvePublicKey ):
126
+ curve_name = public_key .curve .name
127
+ curve_map = {
128
+ "secp256r1" : 1 , # NIST P-256
129
+ "secp384r1" : 2 , # NIST P-384
130
+ "secp521r1" : 3 , # NIST P-521
131
+ "brainpoolP256r1" : 8 , # Brainpool P-256
132
+ "brainpoolP384r1" : 9 , # Brainpool P-384
133
+ "brainpoolP512r1" : 10 , # Brainpool P-512
134
+ # Add more curve mappings as needed
135
+ }
136
+ curve_identifier = curve_map .get (curve_name )
123
137
124
- y = public_key .public_numbers ().y .to_bytes (
125
- (public_key .public_numbers ().y .bit_length () + 7 )
126
- // 8 , # Number of bytes needed
127
- "big" , # Byte order
128
- )
138
+ # Extract the x and y coordinates from the public key
139
+ x = public_key .public_numbers ().x .to_bytes (
140
+ (public_key .public_numbers ().x .bit_length () + 7 )
141
+ // 8 , # Number of bytes needed
142
+ "big" , # Byte order
143
+ )
129
144
130
- devicekeyinfo = {
131
- 1 : 2 ,
132
- - 1 : curve_identifier ,
133
- - 2 : x ,
134
- - 3 : y ,
135
- }
145
+ y = public_key .public_numbers ().y .to_bytes (
146
+ (public_key .public_numbers ().y .bit_length () + 7 )
147
+ // 8 , # Number of bytes needed
148
+ "big" , # Byte order
149
+ )
136
150
137
- else :
138
- devicekeyinfo : CoseKey = devicekeyinfo
151
+ devicekeyinfo = {
152
+ 1 : 2 ,
153
+ - 1 : curve_identifier ,
154
+ - 2 : x ,
155
+ - 3 : y ,
156
+ }
157
+ elif isinstance (public_key , Ed25519PublicKey ):
158
+ devicekeyinfo = {
159
+ 1 : 1 , # OKPKey
160
+ - 1 : "Ed25519" , # Curve identifier for Ed25519
161
+ - 2 : public_key .public_bytes (
162
+ encoding = serialization .Encoding .Raw ,
163
+ format = serialization .PublicFormat .Raw
164
+ )
165
+ }
166
+ elif isinstance (public_key , RSAPublicKey ):
167
+ devicekeyinfo = {
168
+ 1 : 3 , # RSAKey
169
+ - 1 : public_key .public_numbers ().n .to_bytes (
170
+ (public_key .public_numbers ().n .bit_length () + 7 ) // 8 ,
171
+ "big"
172
+ ),
173
+ - 2 : public_key .public_numbers ().e .to_bytes (
174
+ (public_key .public_numbers ().e .bit_length () + 7 ) // 8 ,
175
+ "big"
176
+ )
177
+ }
178
+ else :
179
+ raise TypeError ("Loaded public key is not an EllipticCurvePublicKey" )
139
180
140
181
if self .hsm :
141
182
msoi = MsoIssuer (
@@ -149,7 +190,8 @@ def new(
149
190
alg = self .alg ,
150
191
kid = self .kid ,
151
192
validity = validity ,
152
- revocation = revocation
193
+ revocation = revocation ,
194
+ cert_info = self .cert_info
153
195
)
154
196
155
197
else :
@@ -159,10 +201,11 @@ def new(
159
201
alg = self .alg ,
160
202
cert_path = cert_path ,
161
203
validity = validity ,
162
- revocation = revocation
204
+ revocation = revocation ,
205
+ cert_info = self .cert_info
163
206
)
164
207
165
- mso = msoi .sign (doctype = doctype , device_key = devicekeyinfo ,valid_from = datetime .now (timezone .utc ))
208
+ mso = msoi .sign (doctype = doctype , device_key = devicekeyinfo , valid_from = datetime .now (timezone .utc ))
166
209
167
210
mso_cbor = mso .encode (
168
211
tag = False ,
0 commit comments