1
1
from typing import Optional , Union
2
2
3
+ from cbor2 import CBORTag , dumps
4
+
3
5
from cose .algorithms import EdDSA
4
6
from cose .headers import KID , Algorithm
5
7
from cose .keys import CoseKey
10
12
from cose .messages import CoseMessage , Sign1Message
11
13
12
14
from pycardano .address import Address
15
+ from pycardano .crypto import BIP32ED25519PublicKey
13
16
from pycardano .key import (
14
17
PaymentVerificationKey ,
15
18
SigningKey ,
19
+ ExtendedSigningKey ,
20
+ ExtendedVerificationKey ,
16
21
StakeExtendedSigningKey ,
17
22
StakeSigningKey ,
18
23
StakeVerificationKey ,
25
30
26
31
def sign (
27
32
message : str ,
28
- signing_key : SigningKey ,
33
+ signing_key : Union [ ExtendedSigningKey , SigningKey ] ,
29
34
attach_cose_key : bool = False ,
30
35
network : Network = Network .MAINNET ,
31
36
) -> Union [str , dict ]:
@@ -45,7 +50,9 @@ def sign(
45
50
"""
46
51
47
52
# derive the verification key
48
- verification_key = VerificationKey .from_signing_key (signing_key )
53
+ verification_key = signing_key .to_verification_key ()
54
+ if isinstance (verification_key , ExtendedVerificationKey ):
55
+ verification_key = verification_key .to_non_extended ()
49
56
50
57
if isinstance (signing_key , StakeSigningKey ) or isinstance (
51
58
signing_key , StakeExtendedSigningKey
@@ -85,7 +92,20 @@ def sign(
85
92
86
93
msg .key = cose_key # attach the key to the message
87
94
88
- encoded = msg .encode ()
95
+ if isinstance (signing_key , ExtendedSigningKey ):
96
+ message = [
97
+ msg .phdr_encoded ,
98
+ msg .uhdr_encoded ,
99
+ msg .payload ,
100
+ signing_key .sign (msg ._sig_structure ),
101
+ ]
102
+
103
+ encoded = dumps (
104
+ CBORTag (msg .cbor_tag , message ), default = msg ._custom_cbor_encoder
105
+ )
106
+
107
+ else :
108
+ encoded = msg .encode ()
89
109
90
110
# turn the enocded message into a hex string and remove the first byte
91
111
# which is always "d2"
@@ -108,7 +128,9 @@ def sign(
108
128
109
129
110
130
def verify (
111
- signed_message : Union [str , dict ], attach_cose_key : Optional [bool ] = None
131
+ signed_message : Union [str , dict ],
132
+ attach_cose_key : Optional [bool ] = None ,
133
+ extended = False ,
112
134
) -> dict :
113
135
"""Verify the signature of a COSESign1 message and decode its contents following CIP-0008.
114
136
Supports messages signed by browser wallets or `Message.sign()`.
@@ -175,7 +197,16 @@ def verify(
175
197
# attach the key to the decoded message
176
198
decoded_message .key = cose_key
177
199
178
- signature_verified = decoded_message .verify_signature ()
200
+ if extended :
201
+ vk = BIP32ED25519PublicKey (
202
+ public_key = verification_key [:32 ], chain_code = verification_key [32 :]
203
+ )
204
+ vk .verify (
205
+ signature = decoded_message .signature , message = decoded_message ._sig_structure
206
+ )
207
+ signature_verified = True
208
+ else :
209
+ signature_verified = decoded_message .verify_signature ()
179
210
180
211
message = decoded_message .payload .decode ("utf-8" )
181
212
0 commit comments