Usage

In this tutorial you will see how to search for characteristics (e.g., differential or linear characteristics) or zero-probability properties (e.g., impossible differentials or zero-correlation approximations) with the all-in-one functions round_based_ch_search, round_based_cipher_ch_search, round_based_invalidprop_search and round_based_invalidcipherprop_search.

To search for characteristics or zero-probability properties over a primitive, the primitive needs to be implemented following the CASCADA interface. There are several primitives already implemented, such as AES, CHAM, Chaskey, FEAL, HIGHT, LEA, MULTI2, NOEKEON, π-cipher, RECTANGLE, SHACAL-1, SHACAL-2, Simeck, Simon, Speck, SKINNY, TEA, or XTEA (see Primitives implemented). You can find a step-by-step tutorial about implement a new primitive in Adding a primitive.

Note that searching for characteristics or zero-probability properties over a large number of rounds of a complex function such as a block cipher can take a lot of time (e.g., days). Thus, it is recommended to first run a fine-grained search over a small number of rounds and check the results as explained in Advanced Usage.

More information on all the functions and classes of CASCADA can be found in API reference.

Searching for characteristics

Searching for characteristics can be easily done with round_based_ch_search and round_based_cipher_ch_search. For example, searching for optimal (i.e, lowest-weight) XOR differential characteristics covering 2, 3, and 4 rounds of speck_32_64 can be done as follows

>>> from cascada.differential.difference import XorDiff
>>> from cascada.smt.chsearch import ChModelAssertType, PrintingMode, round_based_ch_search
>>> from cascada.primitives import speck
>>> Speck32 = speck.get_Speck_instance(speck.SpeckInstance.speck_32_64)
>>> assert_type = ChModelAssertType.ValidityAndWeight
>>> iterator = round_based_ch_search(Speck32, 2, 3, XorDiff, assert_type, "btor",
...     extra_chfinder_args={"exclude_zero_input_prop": True, "printing_mode": PrintingMode.Silent},
...     extra_findnextchweight_args={"initial_weight": 0})
>>> for (num_rounds, ch) in iterator:
...     print(num_rounds, ":", ch.srepr())
2 : Ch(w=0, id=0040 0000 0000, od=0000 0000 8000)
3 : Ch(w=0, id=0040 0000 0000 0000, od=0000 0000 0000 8000)
4 : Ch(w=0, id=0040 0000 0000 0000, od=0000 0000 0000 8000 8002)

The function round_based_ch_search can be used to search for characteristics for any bit-vector property (e.g., XorDiff, RXDiff or LinearMask), and round_based_cipher_ch_search similarly but for pairs of characteristics (e.g., related-key differential characteristics). See round_based_ch_search and round_based_cipher_ch_search for a detailed explanation of these functions and their parameters.

The submodule chsearch also provides ChFinder and CipherChFinder to search for characteristics with more options and flexibility.

Searching for zero-probability properties

Searching for zero-probability properties can be easily done with round_based_invalidprop_search and round_based_invalidcipherprop_search. For example, searching for zero-correlation hulls covering 4 and 5 rounds of speck_32_64 can be done as follows

>>> from cascada.linear.mask import LinearMask
>>> from cascada.smt.invalidpropsearch import round_based_invalidprop_search, INCREMENT_NUM_ROUNDS
>>> from cascada.primitives import speck
>>> Speck32 = speck.get_Speck_instance(speck.SpeckInstance.speck_32_64)
>>> iterator = round_based_invalidprop_search(Speck32, 4, 5, LinearMask, "btor")
>>> tuple_rounds, tuple_chs = next(iterator)
>>> print(tuple_rounds, ":", ', '.join([ch.srepr() for ch in tuple_chs]))  #  4 rounds
(0, 2, 1, 1) : Ch(w=0, id=0080 4021, od=0201 0200), Ch(w=Infinity, id=0201 0200, od=0000 0001), Ch(w=0, id=0000 0001, od=0004 0004)
>>> iterator.send(INCREMENT_NUM_ROUNDS)  # stop current num_rounds (4) and increment by 1
>>> tuple_rounds, tuple_chs = next(iterator)
>>> print(tuple_rounds, ":", ', '.join([ch.srepr() for ch in tuple_chs]))  #  5 rounds
(0, 2, 1, 2) : Ch(w=0, id=0080 4021, od=0201 0200), Ch(w=Infinity, id=0201 0200, od=0080 4021), Ch(w=0, id=0080 4021, od=0201 0200)

The function round_based_invalidprop_search searches for zero-probability property pairs using a meet-in-the-middle approach, and so does round_based_invalidcipherprop_search but for zero-probability properties of ciphers (e.g., related-key differentials).

To search for zero-probability properties with other automated methods, the submodule invalidpropsearch provides InvalidPropFinder with the methods InvalidPropFinder.find_next_invalidprop_activebitmode and InvalidPropFinder.find_next_invalidprop_quantified_logic, and similarly for InvalidCipherPropFinder.

For example, searching for related-key impossible rotational-XOR differentials using quantified SMT problems over 3-round speck_32_64 can be done as follows

>>> from cascada.differential.difference import RXDiff
>>> from cascada.differential.chmodel import CipherChModel
>>> from cascada.smt.invalidpropsearch import InvalidCipherPropFinder, get_wrapped_cipher_chmodel
>>> from cascada.primitives import speck
>>> Speck32 = speck.get_Speck_instance(speck.SpeckInstance.speck_32_64)
>>> Speck32.set_num_rounds(2)
>>> ch_model = get_wrapped_cipher_chmodel(CipherChModel(Speck32, RXDiff))
>>> invalid_prop_finder = InvalidCipherPropFinder(ch_model, "z3")
>>> uni_inv_ch = next(invalid_prop_finder.find_next_invalidprop_quantified_logic())
>>> print(uni_inv_ch.srepr())
Ch(ks_ch=Ch(w=Infinity, id=c0a2 c0a2, od=0000 0000),  enc_ch=Ch(w=Infinity, id=c0a2 0000, od=c0a2 c0a2))