@@ -457,11 +457,11 @@ def parse_time_delta(self, name):
457457class ParserBinary (ParserBase ):
458458 byte_order = attr .ib (default = ByteOrder .NETWORK , validator = attr .validators .in_ (ByteOrder ))
459459
460- def parse_timestamp (self , name , milliseconds = False ):
461- value , parsed_length = self ._parse_numeric_array (name , 1 , 8 , int )
460+ def parse_timestamp (self , name , milliseconds = False , item_size = 8 ):
461+ value , parsed_length = self ._parse_numeric_array (name , 1 , item_size , int )
462462
463463 self ._parsed_length += parsed_length
464- if value [0 ] == 0xffffffffffffffff :
464+ if value [0 ] == ( 2 ** ( 8 * item_size ) - 1 ) :
465465 self ._parsed_values [name ] = None
466466 else :
467467 value = value [0 ]
@@ -523,22 +523,14 @@ def parse_numeric_flags(self, name, size, flags_class, shift_left=0):
523523 self ._parsed_length += parsed_length
524524 self ._parsed_values [name ] = value
525525
526- def parse_ssh_mpint (self , name ):
527- if self .unparsed_length < 4 :
528- raise NotEnoughData (bytes_needed = 4 - self .unparsed_length )
529-
530- mpint_length , parsed_length = self ._parse_numeric_array (name , 1 , 4 , int )
531- mpint_length = mpint_length [0 ]
532-
533- negative = (mpint_length and (six .indexbytes (self ._parsable , self ._parsed_length + 4 ) >= 0x80 ))
534-
526+ def _parse_mpint (self , mpint_length , mpint_offset , negative ):
535527 if mpint_length % 4 :
536528 pad_byte = six .int2byte (0xff ) if negative else six .int2byte (0x00 )
537529 pad_bytes = (4 - (mpint_length % 4 )) * pad_byte
538530 else :
539531 pad_bytes = b''
540532
541- parsable = pad_bytes + self ._parsable [self ._parsed_length + 4 :]
533+ parsable = pad_bytes + self ._parsable [self ._parsed_length + mpint_offset :]
542534 parser = ParserBinary (parsable )
543535 parser .parse_numeric_array ('mpint_part_array' , (mpint_length + len (pad_bytes )) // 4 , 4 , int )
544536
@@ -549,6 +541,25 @@ def parse_ssh_mpint(self, name):
549541 complement = 1 << (8 * (mpint_length + len (pad_bytes )))
550542 value -= complement
551543
544+ return value
545+
546+ def parse_mpint (self , name , mpint_length ):
547+ value = self ._parse_mpint (mpint_length , 0 , False )
548+
549+ self ._parsed_values [name ] = value
550+ self ._parsed_length += mpint_length
551+
552+ def parse_ssh_mpint (self , name ):
553+ if self .unparsed_length < 4 :
554+ raise NotEnoughData (bytes_needed = 4 - self .unparsed_length )
555+
556+ mpint_length , parsed_length = self ._parse_numeric_array (name , 1 , 4 , int )
557+ mpint_length = mpint_length [0 ]
558+
559+ negative = (mpint_length and (six .indexbytes (self ._parsable , self ._parsed_length + 4 ) >= 0x80 ))
560+
561+ value = self ._parse_mpint (mpint_length , 4 , negative )
562+
552563 self ._parsed_values [name ] = value
553564 self ._parsed_length += parsed_length + mpint_length
554565
@@ -787,7 +798,7 @@ def compose_time_delta(self, value):
787798class ComposerBinary (ComposerBase ):
788799 byte_order = attr .ib (default = ByteOrder .NETWORK , validator = attr .validators .in_ (ByteOrder ))
789800
790- def compose_timestamp (self , value , milliseconds = False ):
801+ def compose_timestamp (self , value , milliseconds = False , item_size = 8 ):
791802 if value is None :
792803 timestamp = 0xffffffffffffffff
793804 else :
@@ -797,7 +808,7 @@ def compose_timestamp(self, value, milliseconds=False):
797808 timestamp *= 1000
798809 timestamp += value .microsecond // 1000
799810
800- return self ._compose_numeric_array ([timestamp , ], 8 )
811+ return self ._compose_numeric_array ([timestamp , ], item_size )
801812
802813 def _compose_numeric_array (self , values , item_size ):
803814 composed_bytes = bytearray ()
@@ -842,33 +853,57 @@ def compose_numeric_flags(self, values, item_size, shift_right=0):
842853 flag |= value >> shift_right
843854 self ._compose_numeric_array ([flag , ], item_size )
844855
845- def compose_ssh_mpint (self , value ):
856+ @staticmethod
857+ def _compose_mpint (value , length , byte_order ):
846858 negative = value < 0
847- array_length = value .bit_length () // 32
848859
849- if value .bit_length () % 32 :
850- array_length += 1
851860 if negative :
852861 positive_value = (1 << ((value .bit_length () // 8 * 8 ) + 8 )) + value
853862 else :
854863 positive_value = value
855864
856865 value_numeric_array = []
857- for mpint_offset in range (0 , array_length * 32 , 32 ):
866+ for mpint_offset in range (0 , length * 32 , 32 ):
858867 value_numeric_array .append (positive_value >> mpint_offset & 0xffffffff )
859868
860- composer = ComposerBinary ()
869+ composer = ComposerBinary (byte_order = byte_order )
861870 composer .compose_numeric_array (reversed (value_numeric_array ), 4 )
862- value_bytes = composer .composed_bytes .lstrip (b'\x00 ' )
863871
864- if value_bytes and bool (value_bytes [0 ] & 0x80 ) != negative :
872+ mpint_bytes = composer .composed_bytes .lstrip (b'\x00 ' )
873+ if byte_order in [ByteOrder .LITTLE_ENDIAN , ByteOrder .NATIVE ]:
874+ mpint_bytes = mpint_bytes .rstrip (b'\x00 ' )
875+
876+ return mpint_bytes
877+
878+ def compose_mpint (self , value , length ):
879+ mpint_bytes = self ._compose_mpint (value , length , self .byte_order )
880+ if length < len (mpint_bytes ):
881+ raise InvalidValue (length , type (self ), 'mpint_length' )
882+
883+ pad_byte = b'\xff ' if value < 0 else b'\x00 '
884+ if self .byte_order in [ByteOrder .BIG_ENDIAN , ByteOrder .NETWORK ]:
885+ self .compose_raw ((length - len (mpint_bytes )) * pad_byte )
886+ self .compose_raw (mpint_bytes )
887+ else :
888+ self .compose_raw (mpint_bytes )
889+ self .compose_raw ((length - len (mpint_bytes )) * pad_byte )
890+
891+ def compose_ssh_mpint (self , value ):
892+ negative = value < 0
893+ length = value .bit_length () // 32
894+ if value .bit_length () % 32 :
895+ length += 1
896+
897+ mpint_bytes = self ._compose_mpint (value , length , self .byte_order )
898+
899+ if mpint_bytes and bool (mpint_bytes [0 ] & 0x80 ) != negative :
865900 pad_byte = b'\xff ' if negative else b'\x00 '
866901 else :
867902 pad_byte = b''
868903
869- self .compose_numeric (len (pad_byte ) + len (value_bytes ), 4 )
870-
871- self ._composed += pad_byte + value_bytes
904+ self .compose_numeric (len (pad_byte ) + len (mpint_bytes ), 4 )
905+ self . compose_raw ( pad_byte )
906+ self .compose_raw ( mpint_bytes )
872907
873908 def compose_parsable (self , value , item_size = None ):
874909 composed = value .compose ()
0 commit comments