55import json
66import os
77
8- from nacl .bindings import crypto_sign_PUBLICKEYBYTES , crypto_sign_SEEDBYTES
98from nacl .encoding import RawEncoder
109from nacl .hash import blake2b
1110from nacl .public import PrivateKey
1211from nacl .signing import SigningKey as NACLSigningKey
1312
13+ from pycardano .crypto .bip32 import BIP32ED25519PrivateKey
1414from pycardano .exception import InvalidKeyTypeException
1515from pycardano .hash import VERIFICATION_KEY_HASH_SIZE , VerificationKeyHash
1616from pycardano .serialization import CBORSerializable
1717
1818__all__ = [
1919 "Key" ,
20+ "ExtendedSigningKey" ,
21+ "ExtendedVerificationKey" ,
2022 "VerificationKey" ,
2123 "SigningKey" ,
24+ "PaymentExtendedSigningKey" ,
25+ "PaymentExtendedVerificationKey" ,
2226 "PaymentSigningKey" ,
2327 "PaymentVerificationKey" ,
2428 "PaymentKeyPair" ,
29+ "StakeExtendedSigningKey" ,
30+ "StakeExtendedVerificationKey" ,
2531 "StakeSigningKey" ,
2632 "StakeVerificationKey" ,
2733 "StakeKeyPair" ,
@@ -132,16 +138,21 @@ def __repr__(self) -> str:
132138 return self .to_json ()
133139
134140
135- class VerificationKey (Key ):
141+ class SigningKey (Key ):
142+ def sign (self , data : bytes ) -> bytes :
143+ signed_message = NACLSigningKey (self .payload ).sign (data )
144+ return signed_message .signature
145+
146+ @classmethod
147+ def generate (cls ) -> SigningKey :
148+ signing_key = PrivateKey .generate ()
149+ return cls (bytes (signing_key ))
136150
137- SIZE = crypto_sign_PUBLICKEYBYTES
138151
152+ class VerificationKey (Key ):
139153 def hash (self ) -> VerificationKeyHash :
140154 """Compute a blake2b hash from the key
141155
142- Args:
143- hash_size: Size of the hash output in bytes.
144-
145156 Returns:
146157 VerificationKeyHash: Hash output in bytes.
147158 """
@@ -152,33 +163,65 @@ def hash(self) -> VerificationKeyHash:
152163 @classmethod
153164 def from_signing_key (cls , key : SigningKey ) -> VerificationKey :
154165 verification_key = NACLSigningKey (bytes (key )).verify_key
155- return cls (bytes (verification_key ))
166+ return cls (
167+ bytes (verification_key ),
168+ key .key_type .replace ("Signing" , "Verification" ),
169+ key .description .replace ("Signing" , "Verification" ),
170+ )
156171
157172
158- class SigningKey (Key ):
173+ class ExtendedSigningKey (Key ):
174+ def sign (self , data : bytes ) -> bytes :
175+ private_key = BIP32ED25519PrivateKey (self .payload [:64 ], self .payload [96 :])
176+ return private_key .sign (data )
159177
160- SIZE = crypto_sign_SEEDBYTES
161178
162- def sign (self , data : bytes ) -> bytes :
163- signed_message = NACLSigningKey (self .payload ).sign (data )
164- return signed_message .signature
179+ class ExtendedVerificationKey (Key ):
180+ def hash (self ) -> VerificationKeyHash :
181+ """Compute a blake2b hash from the key, excluding chain code
182+
183+ Returns:
184+ VerificationKeyHash: Hash output in bytes.
185+ """
186+ return self .to_non_extended ().hash ()
165187
166188 @classmethod
167- def generate (cls ) -> SigningKey :
168- signing_key = PrivateKey .generate ()
169- return cls (bytes (signing_key ))
189+ def from_signing_key (cls , key : ExtendedSigningKey ) -> ExtendedVerificationKey :
190+ return cls (
191+ key .payload [64 :],
192+ key .key_type .replace ("Signing" , "Verification" ),
193+ key .description .replace ("Signing" , "Verification" ),
194+ )
195+
196+ def to_non_extended (self ) -> VerificationKey :
197+ """Get the 32-byte verification with chain code trimmed off
198+
199+ Returns:
200+ VerificationKey: 32-byte verification with chain code trimmed off
201+ """
202+ return VerificationKey (self .payload [:32 ])
170203
171204
172205class PaymentSigningKey (SigningKey ):
173206 KEY_TYPE = "PaymentSigningKeyShelley_ed25519"
174- DESCRIPTION = "Payment Verification Key"
207+ DESCRIPTION = "Payment Signing Key"
175208
176209
177210class PaymentVerificationKey (VerificationKey ):
178211 KEY_TYPE = "PaymentVerificationKeyShelley_ed25519"
179212 DESCRIPTION = "Payment Verification Key"
180213
181214
215+ class PaymentExtendedSigningKey (ExtendedSigningKey ):
216+ KEY_TYPE = "PaymentExtendedSigningKeyShelley_ed25519_bip32"
217+ DESCRIPTION = "Payment Signing Key"
218+
219+
220+ class PaymentExtendedVerificationKey (ExtendedVerificationKey ):
221+ KEY_TYPE = "PaymentExtendedVerificationKeyShelley_ed25519_bip32"
222+ DESCRIPTION = "Payment Verification Key"
223+
224+
182225class PaymentKeyPair :
183226 def __init__ (
184227 self , signing_key : PaymentSigningKey , verification_key : PaymentVerificationKey
@@ -205,14 +248,24 @@ def __eq__(self, other):
205248
206249class StakeSigningKey (SigningKey ):
207250 KEY_TYPE = "StakeSigningKeyShelley_ed25519"
208- DESCRIPTION = "Stake Verification Key"
251+ DESCRIPTION = "Stake Signing Key"
209252
210253
211254class StakeVerificationKey (VerificationKey ):
212255 KEY_TYPE = "StakeVerificationKeyShelley_ed25519"
213256 DESCRIPTION = "Stake Verification Key"
214257
215258
259+ class StakeExtendedSigningKey (ExtendedSigningKey ):
260+ KEY_TYPE = "StakeExtendedSigningKeyShelley_ed25519_bip32"
261+ DESCRIPTION = "Stake Signing Key"
262+
263+
264+ class StakeExtendedVerificationKey (ExtendedVerificationKey ):
265+ KEY_TYPE = "StakeExtendedVerificationKeyShelley_ed25519_bip32"
266+ DESCRIPTION = "Stake Verification Key"
267+
268+
216269class StakeKeyPair :
217270 def __init__ (
218271 self , signing_key : StakeSigningKey , verification_key : StakeVerificationKey
0 commit comments