1111from .cert import Fieldset , dataclass , Union
1212from prettytable import PrettyTable
1313from .utils import concat_to_bytestring , ensure_bytestring
14- from . import (
15- fields as _FIELD ,
16- keys as _KEY ,
17- exceptions as _EX ,
18- utils as _U
19- )
14+ from . import fields as _FIELD , keys as _KEY , exceptions as _EX , utils as _U
15+
2016
2117@dataclass
2218class SignatureFieldset (Fieldset ):
2319 """Fields for SSH Signature"""
24-
20+
2521 DECODE_ORDER = [
2622 "magic_preamble" ,
2723 "sig_version" ,
2824 "public_key" ,
2925 "namespace" ,
3026 "reserved" ,
3127 "hash_algorithm" ,
32- "signature"
28+ "signature" ,
3329 ]
34-
30+
3531 magic_preamble : _FIELD .SshsigField = _FIELD .SshsigField .factory
3632 sig_version : _FIELD .SignatureVersionField = _FIELD .SignatureVersionField .factory
3733 public_key : _FIELD .PublicKeyField = _FIELD .PublicKeyField .factory
38-
34+
3935 namespace : _FIELD .SignatureNamespaceField = _FIELD .SignatureNamespaceField .factory
4036 reserved : _FIELD .ReservedField = _FIELD .ReservedField .factory
41- hash_algorithm : _FIELD .SignatureHashAlgorithmField = _FIELD .SignatureHashAlgorithmField .factory
37+ hash_algorithm : _FIELD .SignatureHashAlgorithmField = (
38+ _FIELD .SignatureHashAlgorithmField .factory
39+ )
4240 signature : _FIELD .SignatureField = _FIELD .SignatureField .factory
4341
4442 def __bytes__ (self ):
4543 return concat_to_bytestring (
4644 bytes (self .magic_preamble ),
4745 bytes (self .namespace ),
4846 bytes (self .reserved ),
49- bytes (self .hash_algorithm )
47+ bytes (self .hash_algorithm ),
5048 )
51-
49+
5250 def format_pubkey (self ):
53- pubkey = self .public_key .value .to_string ().split (' ' )
54-
55- return _FIELD .StringField .encode (concat_to_bytestring (
56- pubkey [0 ],
57- ' ' ,
58- b64decode (pubkey [1 ]))
51+ pubkey = self .public_key .value .to_string ().split (" " )
52+
53+ return _FIELD .StringField .encode (
54+ concat_to_bytestring (pubkey [0 ], " " , b64decode (pubkey [1 ]))
5955 )
60-
61-
56+
6257 # return _FIELD.BytestringField.encode(concat_to_bytestring(
6358 # _FIELD.StringField.encode(pubkey[0]),
6459 # _FIELD.StringField.encode(b64decode(pubkey[1]))
6560 # ))
66-
61+
6762 def bytes_out (self ):
6863 return concat_to_bytestring (
6964 bytes (self .magic_preamble ),
@@ -72,7 +67,7 @@ def bytes_out(self):
7267 bytes (self .namespace ),
7368 bytes (self .reserved ),
7469 bytes (self .hash_algorithm ),
75- bytes (self .signature )
70+ bytes (self .signature ),
7671 )
7772
7873 @classmethod
@@ -126,29 +121,35 @@ def decode(cls, data: bytes):
126121
127122 return cl_instance , data
128123
124+
129125class SSHSignature :
130126 """
131127 General class for SSH Signatures, used for loading and parsing.
132128 """
129+
133130 data : bytes = None
134-
131+
135132 def __init__ (
136- self , signer_privkey : _KEY .PrivateKey = None ,
137- fields : SignatureFieldset = SignatureFieldset
133+ self ,
134+ signer_privkey : _KEY .PrivateKey = None ,
135+ fields : SignatureFieldset = SignatureFieldset ,
138136 ):
139137 self .fields = fields () if isinstance (fields , type ) else fields
140-
138+
141139 if signer_privkey is not None :
142140 self .fields .replace_field (
143141 "signature" , _FIELD .SignatureField .from_object (signer_privkey )
144142 )
145- self .fields .replace_field ("public_key" , _FIELD .PublicKeyField .from_object (signer_privkey .public_key ))
146-
143+ self .fields .replace_field (
144+ "public_key" ,
145+ _FIELD .PublicKeyField .from_object (signer_privkey .public_key ),
146+ )
147+
147148 if issubclass (type (self .fields .public_key .value ), type (self .fields .public_key )):
148149 self .fields .public_key = self .fields .public_key .value
149150
150151 @classmethod
151- def from_file (cls , path : str , encoding : str = ' none' ) -> "SSHSignature" :
152+ def from_file (cls , path : str , encoding : str = " none" ) -> "SSHSignature" :
152153 """
153154 Loads an existing SSH Signature from a file
154155
@@ -159,13 +160,15 @@ def from_file(cls, path: str, encoding: str = 'none') -> "SSHSignature":
159160 Returns:
160161 SSHSignature: SSH Signature Object
161162 """
162- with open (path , 'rb' if encoding == ' none' else 'r' ) as f :
163+ with open (path , "rb" if encoding == " none" else "r" ) as f :
163164 data = f .read ()
164165
165- return cls .from_string (data , encoding if encoding != ' none' else None )
166-
166+ return cls .from_string (data , encoding if encoding != " none" else None )
167+
167168 @classmethod
168- def from_string (cls , data : Union [str , bytes ], encoding : str = 'utf-8' ) -> "SSHSignature" :
169+ def from_string (
170+ cls , data : Union [str , bytes ], encoding : str = "utf-8"
171+ ) -> "SSHSignature" :
169172 """
170173 Loads an existing SSH Signature from file contents/string
171174
@@ -177,17 +180,17 @@ def from_string(cls, data: Union[str, bytes], encoding: str = 'utf-8') -> "SSHSi
177180 """
178181 if isinstance (data , str ):
179182 data = data .encode (encoding )
180-
181- if b' BEGIN SSH SIGNATURE' in data :
182- data = data .replace (b' -----BEGIN SSH SIGNATURE-----\n ' , b'' )
183-
184- if b' END SSH SIGNATURE' in data :
185- data = data .replace (b' -----END SSH SIGNATURE-----' , b'' )
186-
183+
184+ if b" BEGIN SSH SIGNATURE" in data :
185+ data = data .replace (b" -----BEGIN SSH SIGNATURE-----\n " , b"" )
186+
187+ if b" END SSH SIGNATURE" in data :
188+ data = data .replace (b" -----END SSH SIGNATURE-----" , b"" )
189+
187190 data = data .strip (b"\n \t " )
188-
191+
189192 return cls .decode (b64decode (data ))
190-
193+
191194 @classmethod
192195 def decode (cls , data : bytes ) -> "SSHSignature" :
193196 """
@@ -201,7 +204,7 @@ def decode(cls, data: bytes) -> "SSHSignature":
201204 """
202205 sig_fields , data = SignatureFieldset .decode (data )
203206 return cls (fields = sig_fields )
204-
207+
205208 def get_signable (self , data : Union [str , bytes ]) -> bytes :
206209 """
207210 Returns the signable data for the signature or verification
@@ -218,12 +221,12 @@ def get_signable(self, data: Union[str, bytes]) -> bytes:
218221 raise _EX .InvalidHashAlgorithmException (
219222 f"Unknown hash algorithm { self .fields .hash_algorithm } "
220223 )
221-
224+
222225 return bytes (self .fields ) + _FIELD .StringField .encode (hash )
223-
226+
224227 def get_signable_file (self , path : str ) -> bytes :
225228 """
226- Loads the signable content from a file.
229+ Loads the signable content from a file.
227230 Will be loaded as bytes without encoding.
228231
229232 Args:
@@ -232,11 +235,11 @@ def get_signable_file(self, path: str) -> bytes:
232235 Returns:
233236 bytes: The signable data from the file
234237 """
235- with open (path , 'rb' ) as f :
238+ with open (path , "rb" ) as f :
236239 data = f .read ()
237-
240+
238241 return self .get_signable (data )
239-
242+
240243 def __str__ (self ) -> str :
241244 table = PrettyTable (["Field" , "Value" ])
242245
@@ -257,36 +260,34 @@ def set(self, field: str, data):
257260 return
258261
259262 raise _EX .InvalidCertificateFieldException (f"Unknown field { field } " )
260-
263+
261264 def verify (
262265 self , data , public_key : _KEY .PublicKey = None , raise_on_error : bool = False
263266 ) -> bool :
264267 if not public_key :
265- public_key = self .fields .get ('public_key' , None )
266-
267- public_key .verify (
268- self .get_signable (data ),
269- self .fields .signature .value
270- )
271-
268+ public_key = self .fields .get ("public_key" , None )
269+
270+ public_key .verify (self .get_signable (data ), self .fields .signature .value )
271+
272272 def sign (self , data : Union [str , bytes ]):
273- signable = self .get_signable (data )
273+ signable = self .get_signable (data )
274274 self .fields .signature .sign (signable )
275-
275+
276276 def sign_file (self , path : str ):
277277 signable = self .get_signable_file (path )
278278 self .fields .signature .sign (signable )
279-
279+
280280 def to_string (self ):
281281 content = self .fields .bytes_out ()
282282 content = b64encode (content )
283283 file_content = b"-----BEGIN SSH SIGNATURE-----\n "
284- file_content += b'' .join ([content [i :i + 70 ] + b"\n " for i in range (0 , len (content ), 70 )])
284+ file_content += b"" .join (
285+ [content [i : i + 70 ] + b"\n " for i in range (0 , len (content ), 70 )]
286+ )
285287 file_content += b"-----END SSH SIGNATURE-----"
286-
288+
287289 return file_content
288-
290+
289291 def to_file (self , path : str ):
290- with open (path , 'wb' ) as f :
292+ with open (path , "wb" ) as f :
291293 f .write (self .to_string ())
292-
0 commit comments