Source code for cybox.common.hashes

# Copyright (c) 2017, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.

from mixbox import entities, fields
from mixbox.vendor.six import u

import cybox.bindings.cybox_common as common_binding
from cybox.common import HexBinary, String, VocabString
from cybox.common.vocabs import HashName, VocabField


def _set_hash_type(entity, value):
    """Callback hook to set the hash type based on the length of the value.

    If the `Hash` object already has a type, it is not changed.

    Args:
        entity (Hash): The Hash object being modified.
        value (str): The hash value
    """
    # If the Hash already has a defined type_, exit early:
    if entity.type_:
        return
    if not value or not value.value:
        return
    # The `value` argument should be a HexBinary object, so we look at the
    # string in its `value` field.
    hashlen = len(value.value)
    if hashlen == 32:
        entity.type_ = Hash.TYPE_MD5
    elif hashlen == 40:
        entity.type_ = Hash.TYPE_SHA1
    elif hashlen == 56:
        entity.type_ = Hash.TYPE_SHA224
    elif hashlen == 64:
        entity.type_ = Hash.TYPE_SHA256
    elif hashlen == 96:
        entity.type_ = Hash.TYPE_SHA384
    elif hashlen == 128:
        entity.type_ = Hash.TYPE_SHA512
    else:
        entity.type_ = Hash.TYPE_OTHER


[docs]class Hash(entities.Entity): _binding = common_binding _binding_class = common_binding.HashType _namespace = 'http://cybox.mitre.org/common-2' type_ = VocabField("Type", HashName) simple_hash_value = fields.TypedField("Simple_Hash_Value", HexBinary, postset_hook=_set_hash_type) fuzzy_hash_value = fields.TypedField("Fuzzy_Hash_Value", String) TYPE_MD5 = u("MD5") TYPE_MD6 = u("MD6") TYPE_SHA1 = u("SHA1") TYPE_SHA224 = u("SHA224") TYPE_SHA256 = u("SHA256") TYPE_SHA384 = u("SHA384") TYPE_SHA512 = u("SHA512") TYPE_SSDEEP = u("SSDEEP") TYPE_OTHER = VocabString(u("Other")) def __init__(self, hash_value=None, type_=None, exact=False): """Create a new Hash Object If exact=True, add 'condition="Equals"' to the hash value and type. """ super(Hash, self).__init__() # Set type_ first so that auto-typing will work. self.type_ = type_ if self.type_ == self.TYPE_SSDEEP: self.fuzzy_hash_value = hash_value else: self.simple_hash_value = hash_value if exact: if self.simple_hash_value: self.simple_hash_value.condition = "Equals" if self.type_: self.type_.condition = "Equals" def __str__(self): if self.type_ == self.TYPE_SSDEEP: return str(self.fuzzy_hash_value) else: return str(self.simple_hash_value)
# Other_Type and FuzzyHashes not yet supported. # @classmethod # def object_from_dict(cls, hash_dict): # """Create the Hash object representation from an input dictionary""" # hash = common_binding.HashType() # for hash_key, hash_value in hash_dict.items(): # if hash_key == 'type' : hash.Type = Base_Object_Attribute.object_from_dict(common_binding.StringObjectAttributeType(datatype='String'),hash_value) # if hash_key == 'other_type' : hash.Type = Base_Object_Attribute.object_from_dict(common_binding.StringObjectAttributeType(datatype='String'),hash_value) # if hash_key == 'simple_hash_value' : hash.Simple_Hash_Value = Base_Object_Attribute.object_from_dict(common_binding.HexBinaryObjectAttributeType(datatype='hexBinary'),hash_value) # if hash_key == 'fuzzy_hash_value' : hash.Fuzzy_Hash_Value = Base_Object_Attribute.object_from_dict(common_binding.StringObjectAttributeType(datatype='String'),hash_value) # if hash_key == 'fuzzy_hash_structure': # for fuzzy_hash_structure_dict in hash_value: # fuzzy_hash_structure_object = common_binding.FuzzyHashStructureType() # for fuzzy_key, fuzzy_value in fuzzy_hash_structure_dict.items(): # if fuzzy_key == 'block_size' : fuzzy_hash_structure_object.Block_Size = Base_Object_Attribute.object_from_dict(common_binding.IntegerObjectAttributeType(datatype='Integer'),fuzzy_value) # if fuzzy_key == 'block_hash' : # block_hash_dict = fuzzy_value # block_hash_object = common_binding.FuzzyHashBlockType() # for block_hash_key, block_hash_value in block_hash_dict.items(): # if block_hash_key == 'segment_count' : block_hash_object.Segment_Count = Base_Object_Attribute.object_from_dict(common_binding.IntegerObjectAttributeType(datatype='Integer'),block_hash_value) # if block_hash_key == 'block_hash_value' : # hash_value_dict = block_hash_value # hash_value_object = common_binding.HashValueType() # for hash_value_key, hash_value_value in hash_value_dict.items(): # if hash_value_key == 'simple_hash_value' : hash_value_object.Simple_Hash_Value = Base_Object_Attribute.object_from_dict(common_binding.HexBinaryObjectAttributeType(datatype='hexBinary'),hash_value_value) # if hash_value_key == 'fuzzy_hash_value' : hash_value_object.Fuzzy_Hash_Value = Base_Object_Attribute.object_from_dict(common_binding.StringObjectAttributeType(datatype='String'),hash_value_value) # if hash_value_object.hasContent_(): block_hash_object.Block_Hash_Value = hash_value_object # if block_hash_key == 'segments' : # segments_dict = block_hash_value # segments_object = common_binding.HashSegmentsType() # for segment in segments_dict: # hash_segment_object = common_binding.HashSegmentType() # for segment_key, segment_value in segment.items(): # if segment_key == 'trigger_point' : hash_segment_object.Trigger_Point = Base_Object_Attribute.object_from_dict(common_binding.HexBinaryObjectAttributeType(datatype='hexBinary'),segment_value) # if segment_key == 'segment_hash' : # segment_hash_dict = segment_value # segment_hash_object = common_binding.HashValueType() # for segment_hash_key, segment_hash_value in segment_hash_dict.items(): # if segment_hash_key == 'simple_hash_value' : segment_hash_object.Simple_Hash_Value = Base_Object_Attribute.object_from_dict(common_binding.HexBinaryObjectAttributeType(datatype='hexBinary'),segment_hash_value) # if segment_hash_key == 'fuzzy_hash_value' : segment_hash_object.Fuzzy_Hash_Value = Base_Object_Attribute.object_from_dict(common_binding.StringObjectAttributeType(datatype='String'),segment_hash_value) # if segment_hash_object.hasContent_(): hash_segment_object.Segment_Hash = segment_hash_object # if segment_key == 'raw_segment_content' : hash_segment_object.Raw_Segment_Content = segment_value # if hash_segment_object.hasContent_() : segments_object.add_Segment(hash_segment_object) # if segments_object.hasContent_() : block_hash_object.Segments = segments_object # if block_hash_object.hasContent_() : fuzzy_hash_structure_object.Block_Hash = block_hash_object # if fuzzy_hash_structure_object.hasContent_() : hash.add_Fuzzy_Hash_Structure(fuzzy_hash_structure_object) # # return hash
[docs]class HashList(entities.EntityList): _binding = common_binding _binding_class = common_binding.HashListType _namespace = 'http://cybox.mitre.org/common-2' hashes = fields.TypedField("Hash", Hash, multiple=True) @property def md5(self): return self._get_hash_value(Hash.TYPE_MD5) @md5.setter def md5(self, value): self._set_hash(Hash.TYPE_MD5, value) @property def sha1(self): return self._get_hash_value(Hash.TYPE_SHA1) @sha1.setter def sha1(self, value): self._set_hash(Hash.TYPE_SHA1, value) @property def sha224(self): return self._get_hash_value(Hash.TYPE_SHA224) @sha224.setter def sha224(self, value): self._set_hash(Hash.TYPE_SHA224, value) @property def sha256(self): return self._get_hash_value(Hash.TYPE_SHA256) @sha256.setter def sha256(self, value): self._set_hash(Hash.TYPE_SHA256, value) @property def sha384(self): return self._get_hash_value(Hash.TYPE_SHA384) @sha384.setter def sha384(self, value): self._set_hash(Hash.TYPE_SHA384, value) @property def sha512(self): return self._get_hash_value(Hash.TYPE_SHA512) @sha512.setter def sha512(self, value): self._set_hash(Hash.TYPE_SHA512, value) @property def ssdeep(self): return self._get_hash_value(Hash.TYPE_SSDEEP) @ssdeep.setter def ssdeep(self, value): self._set_hash(Hash.TYPE_SSDEEP, value) def _hash_lookup(self, type_): for h in self: if h.type_ == type_: return h return None def _set_hash(self, type_, value): h = self._hash_lookup(type_) if h: if type_ == Hash.TYPE_SSDEEP: h.fuzzy_hash_value = value else: h.simple_hash_value = value else: self.append(Hash(value, type_)) def _get_hash_value(self, type_): """Return the hash with a given type_, or None""" h = self._hash_lookup(type_) if h: if type_ == Hash.TYPE_SSDEEP: return h.fuzzy_hash_value else: return h.simple_hash_value return None