7
7
8
8
from nacl .signing import SigningKey , VerifyKey
9
9
from nacl .encoding import HexEncoder
10
- from synlink .crypto .exception import CryptoException
10
+ from synlink .crypto .exception import (
11
+ CryptoBaseException ,
12
+ SignatureVerificationError ,
13
+ )
11
14
from synlink .crypto .kind import Kind
12
15
from synlink .crypto .typing import PrivateKey as IPrivateKey
13
16
from synlink .crypto .typing import PublicKey as IPublicKey
21
24
Message = bytes
22
25
Signiture = bytes
23
26
24
- __all__ = ["PublicKey" , "PrivateKey" , "KeyPair" , "create_new_ed25519_key_pair" ,
25
- "create_new_ed25519_key_pair_from_seed" ]
26
-
27
-
27
+ __all__ = [
28
+ "PublicKey" ,
29
+ "PrivateKey" ,
30
+ "KeyPair" ,
31
+ "create_new_ed25519_key_pair" ,
32
+ "create_new_ed25519_key_pair_from_seed" ,
33
+ ]
28
34
29
35
class PublicKey (IPublicKey ):
30
36
"""
31
37
Represents an ED25519 public key, providing methods for verification
32
38
and various conversions. This class wraps nacl.signing.VerifyKey.
33
39
"""
40
+
34
41
def __init__ (self , impl : VerifyKey ):
35
42
"""
36
43
Initializes a PublicKey object.
@@ -41,25 +48,21 @@ def __init__(self, impl: VerifyKey):
41
48
super ().__init__ ()
42
49
self ._impl : VerifyKey = impl
43
50
self ._kind = Kind .ED25519
44
-
45
51
def get_kind (self ) -> Kind :
46
52
"""
47
53
Returns the kind of this cryptographic key.
48
54
"""
49
55
return self ._kind
50
-
51
56
def to_bytes (self ) -> bytes :
52
57
"""
53
58
Converts the public key to its raw byte representation.
54
59
"""
55
60
return bytes (self ._impl )
56
-
57
61
def __bytes__ (self ) -> bytes :
58
62
"""
59
63
Allows the PublicKey object to be converted to bytes using bytes().
60
64
"""
61
65
return self .to_bytes ()
62
-
63
66
@classmethod
64
67
def from_bytes (cls , data : bytes ) -> Self :
65
68
"""
@@ -72,7 +75,28 @@ def from_bytes(cls, data: bytes) -> Self:
72
75
A new PublicKey instance.
73
76
"""
74
77
return cls (VerifyKey (data ))
78
+ def try_verify (self , data : bytes , signature : bytes ) -> bool :
79
+ """
80
+ Attempts to verify the signature against the signed message.
81
+
82
+ Args:
83
+ data: The original message bytes that were signed.
84
+ signature: The raw signature bytes.
85
+
86
+ Returns:
87
+ True if the signature is valid.
75
88
89
+ Raises:
90
+ SignatureVerificationError: If the signature is forged or corrupt.
91
+ CryptoBaseException: For other unexpected verification errors.
92
+ """
93
+ try :
94
+ self ._impl .verify (data , signature )
95
+ return True
96
+ except BadSignatureError as e :
97
+ raise SignatureVerificationError (f"{ e } " ) from e
98
+ except Exception as e :
99
+ raise CryptoBaseException (f"{ e } " ) from e
76
100
def verify (self , data : bytes , signature : bytes ) -> bool :
77
101
"""
78
102
Verifies the signature against the signed message.
@@ -94,31 +118,28 @@ def verify(self, data: bytes, signature: bytes) -> bool:
94
118
# Catch other potential exceptions during verification
95
119
# print(f"An unexpected error occurred during verification: {e}") # For debugging
96
120
return False
97
-
98
-
99
121
def __str__ (self ) -> str :
100
122
"""
101
123
Returns a human-readable string representation of the public key.
102
124
"""
103
- output = self ._impl \
104
- .encode (encoder = HexEncoder ()) \
105
- .decode ('utf-8' )
125
+ output = self ._impl .encode (encoder = HexEncoder ()).decode ("utf-8" )
106
126
return f"PublicKey({ output } )"
107
-
108
127
def __repr__ (self ) -> str :
109
128
"""
110
129
Returns a detailed string representation for debugging.
111
130
"""
112
- output = self ._impl .encode (encoder = HexEncoder ()).decode (' utf-8' )
131
+ output = self ._impl .encode (encoder = HexEncoder ()).decode (" utf-8" )
113
132
# Show a truncated hex representation for brevity in repr
114
- return f"<synlink.crypto.ed25519.PublicKey { output [:8 ]} ...{ output [- 8 :]} >"
115
-
133
+ return (
134
+ f"<synlink.crypto.ed25519.PublicKey { output [:8 ]} ...{ output [- 8 :]} >"
135
+ )
116
136
117
137
class PrivateKey (IPrivateKey ):
118
138
"""
119
139
Represents an ED25519 private key, providing methods for signing
120
140
and various conversions. This class wraps nacl.signing.SigningKey.
121
141
"""
142
+
122
143
def __init__ (self , impl : SigningKey ):
123
144
"""
124
145
Initializes a PrivateKey object.
@@ -129,13 +150,11 @@ def __init__(self, impl: SigningKey):
129
150
super ().__init__ ()
130
151
self ._kind = Kind .ED25519
131
152
self ._impl : SigningKey = impl
132
-
133
153
def get_kind (self ) -> Kind :
134
154
"""
135
155
Returns the kind of this cryptographic key.
136
156
"""
137
157
return self ._kind
138
-
139
158
@classmethod
140
159
def generate (cls ) -> Self :
141
160
"""
@@ -146,7 +165,6 @@ def generate(cls) -> Self:
146
165
"""
147
166
impl = SigningKey .generate ()
148
167
return cls (impl )
149
-
150
168
@classmethod
151
169
def from_seed (cls , seed : Optional [bytes ] = None ) -> Self :
152
170
"""
@@ -171,7 +189,6 @@ def from_seed(cls, seed: Optional[bytes] = None) -> Self:
171
189
), "PrivateKey seed must be a 32 bytes long binary sequence"
172
190
impl = ImplPrivateKey .from_seed (seed )
173
191
return cls (SigningKey (bytes (impl )))
174
-
175
192
@classmethod
176
193
def from_bytes (cls , data : bytes ) -> Self :
177
194
"""
@@ -185,16 +202,14 @@ def from_bytes(cls, data: bytes) -> Self:
185
202
"""
186
203
impl = SigningKey (data )
187
204
return cls (impl )
188
-
189
205
def get_public_key (self ) -> IPublicKey :
190
206
"""
191
207
Returns the public key corresponding to this private key.
192
208
"""
193
209
if not isinstance (self ._impl , SigningKey ):
194
- raise CryptoException ("Invalid private key implementation." )
210
+ raise CryptoBaseException ("Invalid private key implementation." )
195
211
# Return a PublicKey wrapping the VerifyKey derived from this SigningKey
196
212
return PublicKey (self ._impl .verify_key )
197
-
198
213
def sign (self , data : bytes ) -> Tuple [Message , Signiture ]:
199
214
"""
200
215
Signs data with the private key and returns the raw signature.
@@ -206,76 +221,95 @@ def sign(self, data: bytes) -> Tuple[Message, Signiture]:
206
221
The raw signature bytes.
207
222
"""
208
223
if not isinstance (self ._impl , SigningKey ):
209
- raise CryptoException ("Invalid private key implementation." )
224
+ raise CryptoBaseException ("Invalid private key implementation." )
210
225
# Direct signing using the wrapped SigningKey
211
226
signed_message = self ._impl .sign (data )
212
227
return signed_message .message , signed_message .signature
213
-
214
228
def to_bytes (self ) -> bytes :
215
229
"""
216
230
Converts the private key to its raw byte representation.
217
231
"""
218
232
return bytes (self ._impl )
219
-
220
233
def __bytes__ (self ) -> bytes :
221
234
"""
222
235
Allows the PrivateKey object to be converted to bytes using bytes().
223
236
"""
224
237
return self .to_bytes ()
225
-
226
238
def __str__ (self ) -> str :
227
239
"""
228
240
Returns a human-readable string representation of the private key.
229
241
"""
230
242
# For security, avoid showing private key material in str.
231
243
return "PrivateKey(ED25519)"
232
-
233
244
def __repr__ (self ) -> str :
234
245
"""
235
246
Returns a detailed string representation for debugging.
236
247
"""
237
248
# For security, avoid showing private key material in repr.
238
249
return "<synlink.crypto.ed25519.PrivateKey>"
239
250
240
-
241
251
@dataclass (frozen = True , repr = False )
242
252
class KeyPair (object ):
243
253
"""
244
254
Represents an ED25519 key pair, containing both a private and public key.
245
255
"""
246
- secret : PrivateKey
247
- public : PublicKey
248
256
249
- def try_verify (self , message : bytes , signature : bytes ) -> bool :
250
- try :
251
- return self .public .verify (data = message , signature = signature )
252
- except BadSignatureError as e :
253
- raise e
257
+ secret : PrivateKey
258
+ public : PublicKey
259
+
260
+ def try_verify (self , message : bytes , signature : bytes ) -> bool :
261
+ """
262
+ Try to verifies the signature against the signed message.
263
+
264
+ Args:
265
+ data: The original message bytes that were signed.
266
+ signature: The raw signature bytes.
254
267
255
- def verify (self , message : bytes , signature : bytes ) -> bool :
268
+ Returns:
269
+ Always True if the signature is valid.
270
+
271
+ Rasies:
272
+ BadSignatureError: Signature was forged or otherwise corrupt.
273
+ Exception: base class for all non-exit exceptions.
274
+ """
275
+ return self .public .try_verify (data = message , signature = signature )
276
+ def verify (self , message : bytes , signature : bytes ) -> bool :
277
+ """
278
+ Verifies the signature against the signed message.
279
+
280
+ Args:
281
+ data: The original message bytes that were signed.
282
+ signature: The raw signature bytes.
283
+
284
+ Returns:
285
+ True if the signature is valid, False otherwise.
286
+ """
256
287
try :
257
288
return self .public .verify (data = message , signature = signature )
258
289
except BadSignatureError :
259
290
return False
291
+ def sign (self , message : bytes ) -> Tuple [Message , Signiture ]:
292
+ """
293
+ Signs data with the private key and returns the raw signature.
260
294
261
- def sign (self , message : bytes ) -> Tuple [Message , Signiture ]:
262
- return self .secret .sign (
263
- data = message
264
- )
295
+ Args:
296
+ data: The message bytes to sign.
265
297
298
+ Returns:
299
+ The raw signature bytes.
300
+ """
301
+ return self .secret .sign (data = message )
266
302
def __bytes__ (self ) -> bytes :
267
303
"""
268
304
Returns the raw bytes of the secret (private) key.
269
305
"""
270
306
return bytes (self .secret )
271
-
272
307
def __repr__ (self ) -> str :
273
308
"""
274
309
Returns a detailed string representation for debugging.
275
310
"""
276
311
# Include the public key's repr for better context
277
- return f"<synlink.crypto.ed25519.KeyPair public={ self .public !r} >"
278
-
312
+ return f"<synlink.crypto.ed25519.KeyPair public={ self .public !s} >"
279
313
280
314
def create_new_ed25519_key_pair () -> KeyPair :
281
315
"""
@@ -288,8 +322,9 @@ def create_new_ed25519_key_pair() -> KeyPair:
288
322
public = secret .get_public_key ()
289
323
return KeyPair (secret , public )
290
324
291
-
292
- def create_new_ed25519_key_pair_from_seed (seed : Optional [bytes ] = None ) -> KeyPair :
325
+ def create_new_ed25519_key_pair_from_seed (
326
+ seed : Optional [bytes ] = None ,
327
+ ) -> KeyPair :
293
328
"""
294
329
Creates a new ED25519 key pair from an optional 32-byte seed.
295
330
0 commit comments