11from typing import Optional , Union
22
3+ from cbor2 import CBORTag , dumps
34from cose .algorithms import EdDSA
45from cose .headers import KID , Algorithm
56from cose .keys import CoseKey
1011from cose .messages import CoseMessage , Sign1Message
1112
1213from pycardano .address import Address
14+ from pycardano .crypto import BIP32ED25519PublicKey
1315from pycardano .key import (
16+ ExtendedSigningKey ,
17+ ExtendedVerificationKey ,
1418 PaymentVerificationKey ,
1519 SigningKey ,
1620 StakeExtendedSigningKey ,
1721 StakeSigningKey ,
1822 StakeVerificationKey ,
19- VerificationKey ,
2023)
2124from pycardano .network import Network
2225
2528
2629def sign (
2730 message : str ,
28- signing_key : SigningKey ,
31+ signing_key : Union [ ExtendedSigningKey , SigningKey ] ,
2932 attach_cose_key : bool = False ,
3033 network : Network = Network .MAINNET ,
3134) -> Union [str , dict ]:
@@ -45,7 +48,9 @@ def sign(
4548 """
4649
4750 # derive the verification key
48- verification_key = VerificationKey .from_signing_key (signing_key )
51+ verification_key = signing_key .to_verification_key ()
52+ if isinstance (verification_key , ExtendedVerificationKey ):
53+ verification_key = verification_key .to_non_extended ()
4954
5055 if isinstance (signing_key , StakeSigningKey ) or isinstance (
5156 signing_key , StakeExtendedSigningKey
@@ -85,7 +90,20 @@ def sign(
8590
8691 msg .key = cose_key # attach the key to the message
8792
88- encoded = msg .encode ()
93+ if isinstance (signing_key , ExtendedSigningKey ):
94+ _message = [
95+ msg .phdr_encoded ,
96+ msg .uhdr_encoded ,
97+ msg .payload ,
98+ signing_key .sign (msg ._sig_structure ),
99+ ]
100+
101+ encoded = dumps (
102+ CBORTag (msg .cbor_tag , _message ), default = msg ._custom_cbor_encoder
103+ )
104+
105+ else :
106+ encoded = msg .encode ()
89107
90108 # turn the enocded message into a hex string and remove the first byte
91109 # which is always "d2"
@@ -108,7 +126,8 @@ def sign(
108126
109127
110128def verify (
111- signed_message : Union [str , dict ], attach_cose_key : Optional [bool ] = None
129+ signed_message : Union [str , dict ],
130+ attach_cose_key : Optional [bool ] = None ,
112131) -> dict :
113132 """Verify the signature of a COSESign1 message and decode its contents following CIP-0008.
114133 Supports messages signed by browser wallets or `Message.sign()`.
@@ -175,7 +194,16 @@ def verify(
175194 # attach the key to the decoded message
176195 decoded_message .key = cose_key
177196
178- signature_verified = decoded_message .verify_signature ()
197+ if len (verification_key ) > 32 :
198+ vk = BIP32ED25519PublicKey (
199+ public_key = verification_key [:32 ], chain_code = verification_key [32 :]
200+ )
201+ vk .verify (
202+ signature = decoded_message .signature , message = decoded_message ._sig_structure
203+ )
204+ signature_verified = True
205+ else :
206+ signature_verified = decoded_message .verify_signature ()
179207
180208 message = decoded_message .payload .decode ("utf-8" )
181209
0 commit comments