
    <i]              	          S r SSKrSSKrSSKrSSKrSSKJrJrJr  SSK	J
r
Jr  SSKJr  \R                  " \5      r0 SSSS	S	S
4S jr0 SSS	S	S
4S jrS rS rS rS rS rS rS rS rS rS rS rS rSES jrS r 0 SS\4S\4S._SS\4S \4S!._S"S\4S \4S._S#S$\4S$\4S\4S%._S&S\4S$\4S$\4S'._S(S\4S\4S._S)S*\4S+\4S,\4S
S-._S.S$\4S\4S$\4S/._S0S1\4S2\4S2\4S3S4._S5S$\4S+\4S6._S7S$\4S\4S$\4S8._S9S$\4S \4S \4S:._S;S\4S<\4S\4S
S=._S>S,\4S,\4S \4S$\4S$\4S<\4S?._S@S\4S$\4S$\4SA._SBS$\4S+\4SC._SDS\4S\4S._r!g)FzHPython APIs for STIX 2 Object-based Semantic Equivalence and Similarity.    N   )
DataSourceDataStoreMixinFilter)STIXdatetimeparse_into_datetime   equivalent_patternsF   F   c	           
      .    [        XX$XVXx40 U	D6n
X:  a  gg)a  This method returns a true/false value if two objects are semantically equivalent.
Internally, it calls the object_similarity function and compares it against the given
threshold value.

Args:
    obj1: A stix2 object instance
    obj2: A stix2 object instance
    prop_scores: A dictionary that can hold individual property scores,
        weights, contributing score, matching score and sum of weights.
    threshold: A numerical value between 0 and 100 to determine the minimum
        score to result in successfully calling both objects equivalent. This
        value can be tuned.
    ds1 (optional): A DataStore object instance from which to pull related objects
    ds2 (optional): A DataStore object instance from which to pull related objects
    ignore_spec_version: A boolean indicating whether to test object types
        that belong to different spec versions (STIX 2.0 and STIX 2.1 for example).
        If set to True this check will be skipped.
    versioning_checks: A boolean indicating whether to test multiple revisions
        of the same object (when present) to maximize similarity against a
        particular version. If set to True the algorithm will perform this step.
    max_depth: A positive integer indicating the maximum recursion depth the
        algorithm can reach when de-referencing objects and performing the
        object_similarity algorithm.
    weight_dict: A dictionary that can be used to override what checks are done
        to objects in the similarity process.

Returns:
    bool: True if the result of the object similarity is greater than or equal to
        the threshold value. False otherwise.

Warning:
    Object types need to have property weights defined for the similarity process.
    Otherwise, those objects will not influence the final score. The WEIGHTS
    dictionary under `stix2.equivalence.object` can give you an idea on how to add
    new entries and pass them via the `weight_dict` argument. Similarly, the values
    or methods can be fine tuned for a particular use case.

Note:
    Default weight_dict:

    .. include:: ../../similarity_weights.rst

Note:
    This implementation follows the Semantic Equivalence Committee Note.
    see `the Committee Note <link here>`__.

TF)object_similarity)obj1obj2prop_scores	thresholdds1ds2ignore_spec_versionversioning_checks	max_depthweight_dictsimilarity_results              [/home/james-whalen/.local/lib/python3.13/site-packages/stix2/equivalence/object/__init__.pyobject_equivalencer      s0    h *Kc(3 %    c           
         [         R                  5       n	U(       a  U	R                  U5        UUUUUS.U	S'   U S   US   pX:w  a  [        S5      eUSL a1  U R	                  SS5      UR	                  SS5      :w  a  [        S5      e X      X   S	   n[
        R                  S
U S   US   5         U" XU40 X   D6u  p[
        R                  SX5        US::  a  gX-  S-  nU$ ! [         a    U" X40 X   D6u  p N?f = f! [         Ga    [
        R                  S
U S   US   5        SnSnX    GHr  n[        XU5      (       d  M  X   U   S   nX   U   S   n0 X/'   U[        :X  a  UU" X   X   X   S   5      -  nOU[        :X  a#  X   S   nUU" U S   U S   US   US   U5      -  nOU[        :X  d
  U[        :X  a  US:  a  US-
  U	S   S'   U	S   S   U	S   S   pC[        X45      (       a  UU" X   X   X440 U	D6-  nOAU[        :X  a  [        nUU" X   X   5      -  nO U[        :X  a  [         nUU" X   X   5      -  nUR"                  X/   S'   OGM*  XyS   S'   OUU" X   X   5      -  nUU-  nUW-  nUX/   S'   UX/   S'   [
        R                  SUUU5        GMu     XS'   XS'   [
        R                  SX5         GNf = f! [         a    [
        R%                  SU
5        S=p GNf = f)a  This method returns a measure of similarity depending on how
similar the two objects are.

Args:
    obj1: A stix2 object instance
    obj2: A stix2 object instance
    prop_scores: A dictionary that can hold individual property scores,
        weights, contributing score, matching score and sum of weights.
    ds1 (optional): A DataStore object instance from which to pull related objects
    ds2 (optional): A DataStore object instance from which to pull related objects
    ignore_spec_version: A boolean indicating whether to test object types
        that belong to different spec versions (STIX 2.0 and STIX 2.1 for example).
        If set to True this check will be skipped.
    versioning_checks: A boolean indicating whether to test multiple revisions
        of the same object (when present) to maximize similarity against a
        particular version. If set to True the algorithm will perform this step.
    max_depth: A positive integer indicating the maximum recursion depth the
        algorithm can reach when de-referencing objects and performing the
        object_similarity algorithm.
    weight_dict: A dictionary that can be used to override what checks are done
        to objects in the similarity process.

Returns:
    float: A number between 0.0 and 100.0 as a measurement of similarity.

Warning:
    Object types need to have property weights defined for the similarity process.
    Otherwise, those objects will not influence the final score. The WEIGHTS
    dictionary under `stix2.equivalence.object` can give you an idea on how to add
    new entries and pass them via the `weight_dict` argument. Similarly, the values
    or methods can be fine tuned for a particular use case.

Note:
    Default weight_dict:

    .. include:: ../../similarity_weights.rst

Note:
    This implementation follows the Semantic Equivalence Committee Note.
    see `the Committee Note <link here>`__.

)r   r   r   r   r   	_internaltypez0The objects to compare must be of the same type!Fspec_versionz2.0z8The objects to compare must be of the same spec version!methodz9Starting object similarity process between: '%s' and '%s'idz&Matching Score: %s, Sum of Weights: %s        r   r   tdeltar   latitude	longituder   r   r   
check_typeweightcontributing_scorez0'%s' check -- weight: %s, contributing score: %smatching_scoresum_weightszU'%s' type has no 'weights' dict specified & thus no object similarity method to call!      Y@)WEIGHTScopyupdate
ValueErrorgetloggerdebug	TypeErrorKeyErrorcheck_property_presentpartial_timestamp_basedpartial_location_distancereference_checklist_reference_check_datastore_checkexact_matchpartial_list_based__name__warning)r   r   r   r   r   r   r   r   r   weightstype1type2r"   r+   r,   propw
comp_functr*   r   equivalence_scores                        r   r   r   K   s   ^ llnG{#  3.GK <f5~KLLe#(G488TbdiKj(jSTT<`
6	`^H-F^ LLTVZ[_V`bfgkblmS.4T._PWP^._+ LLA>_a'5>  S.4T.R7>.R+Sc  ,	`LLTVZ[_V`bfgkblm NK)$d;;t,Q/A!(!5a!8J(*K%!%<<-.DJ
T[TbckTl1m-m*#'@@$+N;$?	-.D<LdS^N_aefpaqsw  yD  tE  GP  2Q  .Q*#6*H\:\$q=@IAGK0='.{';E'BGKDXY^D_/9956DJPTPZ\_9pho9p5p 2!+!>-8
56DJPTPZ9[5[ 2!+/C!C-?
56DJPTPZ9[5[ 2>H>Q>QK-l;$<E,[9-.DJ
1S-S*1$K"&88N23K%h/>PK%&:;LL!SUY[\^pqG 'J -;())4&LLA>_Y,	`  )npuv'((n)s>   K D 2C& &D ?D AK
E>KK#K65K6c                 j   ^^ U S:X  a  [        UU4S jS 5       5      (       a  g gU T;   a  U T;   a  gg)z>Helper method checks if a property is present on both objects.longitude_latitudec              3   D   >#    U  H  oT;   =(       a    UT;   v   M     g 7fN ).0xr   r   s     r   	<genexpr>)check_property_present.<locals>.<genexpr>   s!     J0I1Dy&Q$Y&0Is    )r&   r'   TF)all)rD   r   r   s    ``r   r7   r7      sA    ##J0IJJJ K  
$$,r   c                    [        U [        5      (       d  [        U 5      n [        U[        5      (       d  [        U5      n[        R                  " U R                  5       5      [        R                  " UR                  5       5      pS[        [        X-
  5      SU-  -  S5      -
  n[        R                  SXX#5        U$ )a  Performs a timestamp-based matching via checking how close one timestamp is to another.

Args:
    t1: A datetime string or STIXdatetime object.
    t2: A datetime string or STIXdatetime object.
    tdelta (float): A given time delta. This number is multiplied by 86400 (1 day) to
        extend or shrink your time change tolerance.

Returns:
    float: Number between 0.0 and 1.0 depending on match criteria.

r   iQ z?--		partial_timestamp_based '%s' '%s' tdelta: '%s'	result: '%s')

isinstancer   r   timemktime	timetupleminabsr3   r4   )t1t2r%   results       r   r8   r8      s     b,'' $b,'' $[[($++blln*ES\UV^4a88F
LLUWY_enMr   c                     [        U 5      [        U5      p2[        UR                  U5      5      [        [        U5      [        U5      5      -  n[        R                  SXU5        U$ )aT  Performs a partial list matching via finding the intersection between
common values. Repeated values are counted only once. This method can be
used for *_refs equality checks when de-reference is not possible.

Args:
    l1: A list of values.
    l2: A list of values.

Returns:
    float: 1.0 if the value matches exactly, 0.0 otherwise.

z---		partial_list_based '%s' '%s'	result: '%s')setlenintersectionmaxr3   r4   )l1l2l1_setl2_setr[   s        r   r>   r>      sR     Wc"gF$$V,-CKV0MMF
LLCRVTMr   c                 F    SnX:X  a  Sn[         R                  SXU5        U$ )a7  Performs an exact value match based on two values. This method can be
used for *_ref equality check when de-reference is not possible.

Args:
    val1: A value suitable for an equality test.
    val2: A value suitable for an equality test.

Returns:
    float: 1.0 if the value matches exactly, 0.0 otherwise.

r$         ?z&--		exact_match '%s' '%s'	result: '%s')r3   r4   )val1val2r[   s      r   r=   r=     s)     F|
LL<d&QMr   c                 h    SSK Jn  UR                  X5      n[        R	                  SXU5        US-  $ )zPerforms a partial string match using the Jaro-Winkler distance algorithm.

Args:
    str1: A string value to check.
    str2: A string value to check.

Returns:
    float: Number between 0.0 and 1.0 depending on match criteria.

r   )fuzzz/--		partial_string_based '%s' '%s'	result: '%s'r-   )	rapidfuzzrj   token_sort_ratior3   r4   )str1str2rj   r[   s       r   partial_string_basedro     s3     ""4.F
LLEtSYZE>r   c                     [        X5      $ )zPerforms a matching on Indicator Patterns.

Args:
    pattern1: An Indicator pattern
    pattern2: An Indicator pattern

Returns:
    float: Number between 0.0 and 1.0 depending on match criteria.

r
   )pattern1pattern2s     r   custom_pattern_basedrs   +  s     x22r   c                 t   1 SknSn[         R                  " [         R                  " X5      5      nU H  u  pVSnSnSn	Sn
[        SXV5      (       a  US   US   :X  a  US   n
Sn[        SXV5      (       a  US   US   :X  a  Sn[        SXV5      (       a  US   US   :X  a  Sn	U(       a0  U(       d  U	(       a"  X;   a  S	n[        R                  S
XU5        Us  $ U(       d  U(       d	  U	(       d  M  X;  d  M  US-  nM     U[        [        U 5      [        U5      5      -  n[        R                  S
XU5        U$ )zPerforms a matching on External References.

Args:
    ext_refs1: A list of external references.
    ext_refs2: A list of external references.

Returns:
    float: Number between 0.0 and 1.0 depending on matches.

>   cvecapecverismitre-attackr   FNsource_nameTexternal_idurlrf   z;--		partial_external_reference_based '%s' '%s'	result: '%s'r   )	itertoolschainproductr7   r3   r4   r`   r^   )	ext_refs1	ext_refs2allowedmatches	ref_pairsext_ref1ext_ref2sn_matchei_match	url_matchry   r[   s               r    partial_external_reference_basedr   9  s?    8GG)/I (	!-DD&(=*AA&}5!-DD&(=*AA!%<<(5/1 	
 YK4JFLLPf M II;3MqLG? (B s3y>3y>::F
LLHf Mr   c                     SSK JnJ n  U" X4X#4UR                  S9nSXt-  -
  n[        R	                  SX4X#4XH5        U$ )a  Given two coordinates perform a matching based on its distance using the Haversine Formula.

Args:
    lat1: Latitude value for first coordinate point.
    lat2: Latitude value for second coordinate point.
    long1: Longitude value for first coordinate point.
    long2: Longitude value for second coordinate point.
    threshold (float): A kilometer measurement for the threshold distance between these two points.

Returns:
    float: Number between 0.0 and 1.0 depending on match.

r   )Unit	haversine)unitr   zD--		partial_location_distance '%s' '%s' threshold: '%s'	result: '%s')r   r   
KILOMETERSr3   r4   )	lat1long1lat2long2r   r   r   distancer[   s	            r   r9   r9   t  sK     *$DOOLH(&'F
LLQ	}i Mr   c                    0 n[        [        UR                  [        SSU 5      /5      5      [        UR                  [        SSU5      /5      5      U5      nUS   S   nUS   S   nUS   S   n	U H6  u  p[	        X4X#UUU	S.UD6nX;  a  XS.XP'   M#  XU    S	   :  d  M0  XS.XP'   M8     UR                  U 0 5      R                  S	S
5      n[        R                  SXU5        U$ )zpChecks multiple object versions if present in graph.
Maximizes for the similarity score of a particular version.r#   =r   r   r   r   r   r   r   r   r   matchedvaluer   r$   z,--		_versioned_checks '%s' '%s'	result: '%s')_object_pairs_bucket_per_typequeryr   r   r2   r3   r4   )ref1ref2r   r   rA   resultspairsr   r   r   object1object2r[   s                r   _versioned_checksr     s    GF4d$;#<=>F4d$;#<=>E
 "+./DE,-@A$[1I!"
"% 3/	
 $+	
 (,>GMdmG,,(,>GM " [[r"&&w4F
LL9F Mr   c           	         U R                  S5      S   UR                  S5      S   peSnXV:X  ax  XT;   as  US   S   nUS   S   n	US   S   n
U	(       a  [        XX#40 UD6S-  nOCUR                  U 5      UR                  U5      pU(       a  U(       a  [        X4X#UU	U
S	.UD6S-  n[        R                  S
XU5        U$ )z|For two references, de-reference the object and perform object_similarity.
The score influences the result of an edge check.--r   r$   r   r   r   r   r-   r   z*--		reference_check '%s' '%s'	result: '%s')splitr   r2   r   r3   r4   )r   r   r   r   rA   rB   rC   r[   r   r   r   o1o2s                r   r:   r:     s     ::d#A&

4(8(;5F~%*%k23HI#K01DEK(5	&t3GwG%OFWWT]CGGDMb* #(;&7'	 ,3	
  LL7F Mr   c                    0 n[        [        U S5      [        US5      U5      nU H}  u  pxUR                  S5      S   UR                  S5      S   pX:X  d  M3  [        XxX#40 UD6nXu;  a  XS.XW'   OXU   S   :  a  XS.XW'   X;  a  X{S.XX'   Mj  XU   S   :  d  Mw  X{S.XX'   M     Sn[	        S UR                  5        5       5      n[        U5      nUS:  a  X-  n[        R                  SXXU5        U$ )	a  For objects that contain multiple references (i.e., object_refs) perform
the same de-reference procedure and perform object_similarity.
The score influences the objects containing these references. The result is
weighted on the amount of unique objects that could 1) be de-referenced 2) id-splitr   r   r   r   r$   c              3   *   #    U  H	  oS    v   M     g7f)r   NrL   )rM   rN   s     r   rO   'list_reference_check.<locals>.<genexpr>  s     9(81gJ(8s   zO--		list_reference_check '%s' '%s'	total_sum: '%s'	max_score: '%s'	result: '%s')	r   r   r   r:   sumvaluesr^   r3   r4   )refs1refs2r   r   rA   r   r   r   r   rB   rC   scorer[   	total_sum	max_scores                  r   r;   r;     s   
 G
+
+E 
zz$'*DJJt,<Q,?u>#DDGDE",0 Aw//,0 A",0 Aw//,0 A  F9(899IGI1}&
LL^iF Mr   c                     [        U R                  [        [        45      (       d%  [        UR                  [        [        45      (       a  gg)NTF)
issubclass	__class__r   r   )r   r   s     r   r<   r<     s4    3==>:">??3==>:">??r   c                     [         R                  " [        5      nUS:X  a(  U  Vs/ s H  o2US      R                  U5      PM       nU$ US:X  a5  U  Vs/ s H(  o2UR	                  S5      S      R                  U5      PM*       nU$ s  snf s  snf )zGiven a list of objects or references, bucket them by type.
Depending on the list type: extract from 'type' property or using
the 'id'.
r    r   r   r   )collectionsdefaultdictlistappendr   )graphmodebucketsobjs       r   r   r     s    
 %%d+Gv~5:;UcV		$	$S	)U; N 
	<ABES4#	$	+	+C	0EBN 	<Bs    B/Bc                   ^ ^ [        T R                  5       5      R                  TR                  5       5      nUR                  UR                  5       5      n[        R                  R                  U U4S jU 5       5      $ )zReturns a generator with the product of the comparable
objects for the graph similarity process. It determines
objects in common between graphs and objects with weights.
c              3   ^   >#    U  H"  n[         R                  " TU   TU   5      v   M$     g 7frK   )r|   r~   )rM   	stix_typegraph1graph2s     r   rO    _object_pairs.<locals>.<genexpr>  s2      )'I 	&+VI->??'s   *-)r]   keysr_   r|   r}   from_iterable)r   r   rA   types_in_commontestable_typess   ``   r   r   r     s`    
 &++-(55fkkmDO$11',,.AN??(( )')  r   zattack-pattern   )nameexternal_referencescampaign<   (   )r   aliaseszcourse-of-actiongrouping   )r   contextobject_refsidentity)r   identity_classsectorsincident	indicator   P      )indicator_typespattern
valid_fromr%   zintrusion-set)r   r   r   location"   !   g     @@)rI   regioncountryr   malware)malware_typesr   zmarking-definition)r   
definitiondefinition_typerelationship)relationship_type
source_ref
target_refreport
   )r   	publishedr   r%   sighting)
first_seen	last_seensighting_of_refobserved_data_refswhere_sighted_refssummaryzthreat-actor)r   threat_actor_typesr   tool)
tool_typesr   vulnerability)r    )"__doc__r   r|   loggingrT   	datastorer   r   r   utilsr   r   r   r   	getLoggerr?   r3   r   r   r7   r8   r>   r=   ro   rs   r   r9   r   r:   r;   r<   r   r   r.   rL   r   r   <module>r      sy   N     ; ; 6 )			8	$ "$%q:| DdEP.&&"38v0D:'T
U)* "$DEU
 )**+U )* "$DEU )*,-01U$ )*{+*+%U. )* "$DE/U6  23,-12	7UB )* "$DE*+CUL !#<={#$	MUX 01)*YU` [!;',aUj  +.?+?+kUt )*1201	uU@ 12010!#78!#78$AUP )*!#56*+QUZ -.)*[Ub )* "$DEcUr   