Loading CHANGELOG.md +6 −0 Original line number Diff line number Diff line # Changelog ## 0.8.2 - SSH (`ssh`) - Public Keys (`pubkeys`) - [HASSH fingerprint](https://engineering.salesforce.com/open-sourcing-hassh-abed3ae5044c/) calculation (\#48) ## 0.8.0 - 2022-01-18 - SSH (`ssh`) Loading README.md +2 −0 Original line number Diff line number Diff line Loading @@ -117,6 +117,8 @@ Only features that cannot be or difficultly implemented by some of the most popu #### Cipher Suites 1. identifies as much encryption algorithms as possible (more than 200, compared to 70+ currently supported by OpenSSH) 2. supports [HASSH fingerprint](https://engineering.salesforce.com/open-sourcing-hassh-abed3ae5044c/) calculation (\#96) ## License Loading cryptoparser/common/base.py +9 −6 Original line number Diff line number Diff line Loading @@ -463,7 +463,7 @@ class VectorString(ArrayBase): vector_param = self.get_param() body_composer = ComposerText(vector_param.encoding) body_composer.compose_parsable_array(self._items, vector_param.separator) body_composer.compose_parsable_array(self._items, vector_param.separator, vector_param.fallback_class) header_composer = ComposerBinary() header_composer.compose_numeric(body_composer.composed_length, self.param.item_num_size) Loading Loading @@ -677,7 +677,7 @@ class StringEnumParsableBase(ParsableBaseNoABC): enum_items.sort(key=lambda color: len(color.value.code), reverse=True) try: code = parsable.decode('ascii') code = six.ensure_text(parsable, 'ascii') except UnicodeDecodeError as e: six.raise_from(InvalidValue(parsable, cls), e) Loading @@ -688,7 +688,7 @@ class StringEnumParsableBase(ParsableBaseNoABC): raise InvalidValue(parsable, cls, 'code') def compose(self): return self._asdict().encode('ascii') return six.ensure_binary(self._asdict(), 'ascii') def _asdict(self): return getattr(self, 'value').code Loading Loading @@ -783,7 +783,10 @@ class OpaqueEnumParsable(Vector): @classmethod def _parse(cls, parsable): opaque, parsed_length = super(OpaqueEnumParsable, cls)._parse(parsable) code = bytearray(opaque).decode(cls.get_encoding()) code = six.ensure_text( b''.join([six.int2byte(opaque_item) for opaque_item in opaque]), cls.get_encoding() ) try: parsed_object = next(iter([ Loading @@ -792,7 +795,7 @@ class OpaqueEnumParsable(Vector): if enum_item.value.code == code ])) except StopIteration as e: six.raise_from(InvalidValue(code.encode(cls.get_encoding()), cls), e) six.raise_from(InvalidValue(code, cls), e) return parsed_object, parsed_length Loading @@ -812,7 +815,7 @@ class OpaqueEnumComposer(enum.Enum): def compose(self): composer = ComposerBinary() value = self.value.code.encode(self.get_encoding()) # pylint: disable=no-member value = six.ensure_binary(self.value.code, self.get_encoding()) # pylint: disable=no-member composer.compose_bytes(value, 1) Loading cryptoparser/common/parse.py +28 −17 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ import dateutil import dateutil.parser import dateutil.tz from cryptoparser.common.exception import NotEnoughData, TooMuchData, InvalidValue from cryptoparser.common.exception import NotEnoughData, TooMuchData, InvalidType, InvalidValue import cryptoparser.common.utils Loading Loading @@ -155,7 +155,7 @@ class ParserBase(collections_abc.Mapping): value = self._parsable[self._parsed_length:self._parsed_length + parsable_length] try: value = value.decode(encoding) value = six.ensure_text(value, encoding) if converter != str: value = converter(value) self._parsed_values[name] = value Loading @@ -180,7 +180,7 @@ class ParserText(ParserBase): min_count, max_count ): separators = separators.encode(self._encoding) separators = six.ensure_binary(separators, self._encoding) count = 0 actual_offset = count_offset Loading Loading @@ -273,14 +273,14 @@ class ParserText(ParserBase): may_end): try: if not isinstance(item_class, type): item = item_class(self._parsable[item_offset:item_end].decode(self._encoding)) item = item_class(six.ensure_text(self._parsable[item_offset:item_end], self._encoding)) elif issubclass(item_class, ParsableBaseNoABC): item, parsed_length = item_class.parse_immutable(self._parsable[item_offset:item_end]) item_end = item_offset + parsed_length elif issubclass(item_class, str): item = self._parsable[item_offset:item_end].decode(self._encoding) elif issubclass(item_class, six.string_types): item = six.ensure_text(self._parsable[item_offset:item_end], self._encoding) else: item = item_class(self._parsable[item_offset:item_end].decode(self._encoding)) item = item_class(six.ensure_text(self._parsable[item_offset:item_end], self._encoding)) except (InvalidValue, ValueError, UnicodeError) as e: if fallback_class is not None: parsed_value, parsed_length = self._parse_string_until_separator( Loading @@ -304,7 +304,7 @@ class ParserText(ParserBase): separator_spaces='' ): item_end = None byte_separators = [separator.encode(self._encoding) for separator in separators] byte_separators = [six.ensure_binary(separator, self._encoding) for separator in separators] for separator_end in range(item_offset, len(self._parsable) + 1): for separator in byte_separators: Loading @@ -320,7 +320,7 @@ class ParserText(ParserBase): item_end = len(self._parsable) separator_space_count = 0 byte_separator_spaces = separator_spaces.encode(self._encoding) byte_separator_spaces = six.ensure_binary(separator_spaces, self._encoding) while (item_end > item_offset and self._parsable[ item_end - separator_space_count - 1: Loading Loading @@ -427,7 +427,7 @@ class ParserText(ParserBase): def parse_date_time(self, name): try: value = self._parsable[self._parsed_length:] date_time = dateutil.parser.parse(value.decode(self._encoding)) date_time = dateutil.parser.parse(six.ensure_text(value, self._encoding)) except ValueError as e: six.raise_from(InvalidValue(value, type(self), 'value'), e) Loading Loading @@ -646,7 +646,7 @@ class ComposerBase(object): return len(self._composed) def _compose_string_array(self, values, encoding, separator): separator = bytearray(separator.encode(encoding)) separator = bytearray(six.ensure_binary(separator, encoding)) composed_str = bytearray() for value in values: Loading @@ -654,7 +654,7 @@ class ComposerBase(object): if isinstance(value, ParsableBaseNoABC): composed_str += value.compose() else: composed_str += six.text_type(value).encode(encoding) composed_str += six.ensure_binary(six.text_type(value), encoding) except UnicodeError as e: six.raise_from(InvalidValue(value, type(self)), e) Loading @@ -674,7 +674,7 @@ class ComposerText(ComposerBase): for value in values: composed_str += '{:d}{}'.format(value, separator) self._composed += composed_str[:len(composed_str) - len(separator)].encode(self._encoding) self._composed += six.ensure_binary(composed_str[:len(composed_str) - len(separator)], self._encoding) def compose_numeric(self, value): self._compose_numeric_array([value, ], separator='') Loading @@ -691,10 +691,21 @@ class ComposerText(ComposerBase): def compose_parsable(self, value): self._composed += value.compose() def compose_parsable_array(self, values, separator=','): separator = separator.encode(self._encoding) def compose_parsable_array(self, values, separator=',', fallback_class=None): separator = six.ensure_binary(separator, self._encoding) self._composed += bytearray(separator).join(map(lambda item: item.compose(), values)) composed_items = [] for item in values: if isinstance(item, (ComposerBase, ParsableBase, ParsableBaseNoABC)): composed_item = item.compose() elif fallback_class is not None and isinstance(item, fallback_class): composed_item = six.ensure_binary(item, self._encoding) else: raise InvalidType() composed_items.append(composed_item) self._composed += bytearray(separator).join(composed_items) def compose_separator(self, value): self.compose_string(value) Loading Loading @@ -768,7 +779,7 @@ class ComposerBinary(ComposerBase): def compose_string(self, value, encoding, item_size): try: value = value.encode(encoding) value = six.ensure_binary(value, encoding) except UnicodeError as e: six.raise_from(InvalidValue(value, type(self)), e) Loading cryptoparser/common/utils.py +11 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,8 @@ import inspect import six def get_leaf_classes(base_class): Loading @@ -18,3 +20,12 @@ def get_leaf_classes(base_class): return subclasses return _get_leaf_classes(base_class) def bytes_to_hex_string(byte_array, separator='', lowercase=False): if lowercase: format_str = '{:02x}' else: format_str = '{:02X}' return separator.join([format_str.format(x) for x in six.iterbytes(byte_array)]) Loading
CHANGELOG.md +6 −0 Original line number Diff line number Diff line # Changelog ## 0.8.2 - SSH (`ssh`) - Public Keys (`pubkeys`) - [HASSH fingerprint](https://engineering.salesforce.com/open-sourcing-hassh-abed3ae5044c/) calculation (\#48) ## 0.8.0 - 2022-01-18 - SSH (`ssh`) Loading
README.md +2 −0 Original line number Diff line number Diff line Loading @@ -117,6 +117,8 @@ Only features that cannot be or difficultly implemented by some of the most popu #### Cipher Suites 1. identifies as much encryption algorithms as possible (more than 200, compared to 70+ currently supported by OpenSSH) 2. supports [HASSH fingerprint](https://engineering.salesforce.com/open-sourcing-hassh-abed3ae5044c/) calculation (\#96) ## License Loading
cryptoparser/common/base.py +9 −6 Original line number Diff line number Diff line Loading @@ -463,7 +463,7 @@ class VectorString(ArrayBase): vector_param = self.get_param() body_composer = ComposerText(vector_param.encoding) body_composer.compose_parsable_array(self._items, vector_param.separator) body_composer.compose_parsable_array(self._items, vector_param.separator, vector_param.fallback_class) header_composer = ComposerBinary() header_composer.compose_numeric(body_composer.composed_length, self.param.item_num_size) Loading Loading @@ -677,7 +677,7 @@ class StringEnumParsableBase(ParsableBaseNoABC): enum_items.sort(key=lambda color: len(color.value.code), reverse=True) try: code = parsable.decode('ascii') code = six.ensure_text(parsable, 'ascii') except UnicodeDecodeError as e: six.raise_from(InvalidValue(parsable, cls), e) Loading @@ -688,7 +688,7 @@ class StringEnumParsableBase(ParsableBaseNoABC): raise InvalidValue(parsable, cls, 'code') def compose(self): return self._asdict().encode('ascii') return six.ensure_binary(self._asdict(), 'ascii') def _asdict(self): return getattr(self, 'value').code Loading Loading @@ -783,7 +783,10 @@ class OpaqueEnumParsable(Vector): @classmethod def _parse(cls, parsable): opaque, parsed_length = super(OpaqueEnumParsable, cls)._parse(parsable) code = bytearray(opaque).decode(cls.get_encoding()) code = six.ensure_text( b''.join([six.int2byte(opaque_item) for opaque_item in opaque]), cls.get_encoding() ) try: parsed_object = next(iter([ Loading @@ -792,7 +795,7 @@ class OpaqueEnumParsable(Vector): if enum_item.value.code == code ])) except StopIteration as e: six.raise_from(InvalidValue(code.encode(cls.get_encoding()), cls), e) six.raise_from(InvalidValue(code, cls), e) return parsed_object, parsed_length Loading @@ -812,7 +815,7 @@ class OpaqueEnumComposer(enum.Enum): def compose(self): composer = ComposerBinary() value = self.value.code.encode(self.get_encoding()) # pylint: disable=no-member value = six.ensure_binary(self.value.code, self.get_encoding()) # pylint: disable=no-member composer.compose_bytes(value, 1) Loading
cryptoparser/common/parse.py +28 −17 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ import dateutil import dateutil.parser import dateutil.tz from cryptoparser.common.exception import NotEnoughData, TooMuchData, InvalidValue from cryptoparser.common.exception import NotEnoughData, TooMuchData, InvalidType, InvalidValue import cryptoparser.common.utils Loading Loading @@ -155,7 +155,7 @@ class ParserBase(collections_abc.Mapping): value = self._parsable[self._parsed_length:self._parsed_length + parsable_length] try: value = value.decode(encoding) value = six.ensure_text(value, encoding) if converter != str: value = converter(value) self._parsed_values[name] = value Loading @@ -180,7 +180,7 @@ class ParserText(ParserBase): min_count, max_count ): separators = separators.encode(self._encoding) separators = six.ensure_binary(separators, self._encoding) count = 0 actual_offset = count_offset Loading Loading @@ -273,14 +273,14 @@ class ParserText(ParserBase): may_end): try: if not isinstance(item_class, type): item = item_class(self._parsable[item_offset:item_end].decode(self._encoding)) item = item_class(six.ensure_text(self._parsable[item_offset:item_end], self._encoding)) elif issubclass(item_class, ParsableBaseNoABC): item, parsed_length = item_class.parse_immutable(self._parsable[item_offset:item_end]) item_end = item_offset + parsed_length elif issubclass(item_class, str): item = self._parsable[item_offset:item_end].decode(self._encoding) elif issubclass(item_class, six.string_types): item = six.ensure_text(self._parsable[item_offset:item_end], self._encoding) else: item = item_class(self._parsable[item_offset:item_end].decode(self._encoding)) item = item_class(six.ensure_text(self._parsable[item_offset:item_end], self._encoding)) except (InvalidValue, ValueError, UnicodeError) as e: if fallback_class is not None: parsed_value, parsed_length = self._parse_string_until_separator( Loading @@ -304,7 +304,7 @@ class ParserText(ParserBase): separator_spaces='' ): item_end = None byte_separators = [separator.encode(self._encoding) for separator in separators] byte_separators = [six.ensure_binary(separator, self._encoding) for separator in separators] for separator_end in range(item_offset, len(self._parsable) + 1): for separator in byte_separators: Loading @@ -320,7 +320,7 @@ class ParserText(ParserBase): item_end = len(self._parsable) separator_space_count = 0 byte_separator_spaces = separator_spaces.encode(self._encoding) byte_separator_spaces = six.ensure_binary(separator_spaces, self._encoding) while (item_end > item_offset and self._parsable[ item_end - separator_space_count - 1: Loading Loading @@ -427,7 +427,7 @@ class ParserText(ParserBase): def parse_date_time(self, name): try: value = self._parsable[self._parsed_length:] date_time = dateutil.parser.parse(value.decode(self._encoding)) date_time = dateutil.parser.parse(six.ensure_text(value, self._encoding)) except ValueError as e: six.raise_from(InvalidValue(value, type(self), 'value'), e) Loading Loading @@ -646,7 +646,7 @@ class ComposerBase(object): return len(self._composed) def _compose_string_array(self, values, encoding, separator): separator = bytearray(separator.encode(encoding)) separator = bytearray(six.ensure_binary(separator, encoding)) composed_str = bytearray() for value in values: Loading @@ -654,7 +654,7 @@ class ComposerBase(object): if isinstance(value, ParsableBaseNoABC): composed_str += value.compose() else: composed_str += six.text_type(value).encode(encoding) composed_str += six.ensure_binary(six.text_type(value), encoding) except UnicodeError as e: six.raise_from(InvalidValue(value, type(self)), e) Loading @@ -674,7 +674,7 @@ class ComposerText(ComposerBase): for value in values: composed_str += '{:d}{}'.format(value, separator) self._composed += composed_str[:len(composed_str) - len(separator)].encode(self._encoding) self._composed += six.ensure_binary(composed_str[:len(composed_str) - len(separator)], self._encoding) def compose_numeric(self, value): self._compose_numeric_array([value, ], separator='') Loading @@ -691,10 +691,21 @@ class ComposerText(ComposerBase): def compose_parsable(self, value): self._composed += value.compose() def compose_parsable_array(self, values, separator=','): separator = separator.encode(self._encoding) def compose_parsable_array(self, values, separator=',', fallback_class=None): separator = six.ensure_binary(separator, self._encoding) self._composed += bytearray(separator).join(map(lambda item: item.compose(), values)) composed_items = [] for item in values: if isinstance(item, (ComposerBase, ParsableBase, ParsableBaseNoABC)): composed_item = item.compose() elif fallback_class is not None and isinstance(item, fallback_class): composed_item = six.ensure_binary(item, self._encoding) else: raise InvalidType() composed_items.append(composed_item) self._composed += bytearray(separator).join(composed_items) def compose_separator(self, value): self.compose_string(value) Loading Loading @@ -768,7 +779,7 @@ class ComposerBinary(ComposerBase): def compose_string(self, value, encoding, item_size): try: value = value.encode(encoding) value = six.ensure_binary(value, encoding) except UnicodeError as e: six.raise_from(InvalidValue(value, type(self)), e) Loading
cryptoparser/common/utils.py +11 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,8 @@ import inspect import six def get_leaf_classes(base_class): Loading @@ -18,3 +20,12 @@ def get_leaf_classes(base_class): return subclasses return _get_leaf_classes(base_class) def bytes_to_hex_string(byte_array, separator='', lowercase=False): if lowercase: format_str = '{:02x}' else: format_str = '{:02X}' return separator.join([format_str.format(x) for x in six.iterbytes(byte_array)])