cascada.differential.characteristic module

Manipulate non-symbolic differential characteristics.

Characteristic

Represent differential characteristics over bit-vector functions.

EncryptionCharacteristic

Represent differential characteristics over encryption functions.

CipherCharacteristic

Represent related-key differential characteristics over ciphers.

class cascada.differential.characteristic.Characteristic(input_diff, output_diff, assign_outdiff_list, ch_model, external_diffs=None, free_diffs=None, empirical_ch_weight=None, empirical_data_list=None, is_valid=True)[source]

Bases: cascada.abstractproperty.characteristic.Characteristic

Represent differential characteristics over bit-vector functions.

Internally, this class is a subclass of abstractproperty.characteristic.Characteristic, where the Property is a Difference type.

As mentioned in abstractproperty.characteristic.Characteristic, the characteristic probability is defined as the product of the propagation probability (differential probability) of the Difference pairs (differentials) \((\Delta_{x_{i}} \mapsto \Delta_{x_{i+1}})\) over \(f_i\). If \(f\) has external variables, the characteristic probability approximates the differential probability of the input-output difference pair of the characteristic averaged over the set of all values of the external variables.

>>> from cascada.bitvector.core import Constant
>>> from cascada.bitvector.operation import RotateLeft
>>> from cascada.differential.difference import XorDiff, RXDiff
>>> from cascada.differential.chmodel import ChModel
>>> from cascada.differential.characteristic import Characteristic
>>> from cascada.primitives import speck
>>> Speck32_KS = speck.get_Speck_instance(speck.SpeckInstance.speck_32_64).key_schedule
>>> Speck32_KS.set_num_rounds(2)
>>> xor_ch_model = ChModel(Speck32_KS, XorDiff, ["dmk0", "dmk1", "dmk2"])
>>> zd = core.Constant(0, width=16)
>>> mk0 = RotateLeft(Constant(1, width=16), 5)  # mk0 >>> 7 == 0b010···0
>>> rr2 = RotateLeft(Constant(1, width=16), 14)  # rr2 == 0b010···0 == d5 == d11 (see ch_model)
>>> xor_ch = Characteristic([mk0, zd, zd], [zd, zd, rr2], [zd, rr2, zd, zd, rr2], xor_ch_model)
>>> xor_ch  
Characteristic(ch_weight=1, assignment_weights=[0, 1, 0, 0, 0],
    input_diff=[0x0020, 0x0000, 0x0000], output_diff=[0x0000, 0x0000, 0x4000],
    assign_outdiff_list=[0x0000, 0x4000, 0x0000, 0x0000, 0x4000])
>>> list(zip(xor_ch.assignment_weights, xor_ch.tuple_assign_outdiff2op_model))  
[(Decimal('0'), (XorDiff(0x0000), XorModelBvAdd([XorDiff(0x0000), XorDiff(0x0000)]))),
(Decimal('1'), (XorDiff(0x4000), XorModelBvAdd([XorDiff(0x4000), XorDiff(0x0000)]))),
(Decimal('0'), (XorDiff(0x0000), XorModelId(XorDiff(0x0000)))),
(Decimal('0'), (XorDiff(0x0000), XorModelId(XorDiff(0x0000)))),
(Decimal('0'), (XorDiff(0x4000), XorModelId(XorDiff(0x4000))))]
>>> rx_ch_model = ChModel(Speck32_KS, RXDiff, ["dmk0", "dmk1", "dmk2"])
>>> zd = RXDiff(core.Constant(0, width=16))
>>> td = RXDiff(core.Constant(3, width=16))
>>> rx_ch = Characteristic([zd, zd, zd], [zd, zd, td], [zd, zd, zd, zd, td], rx_ch_model)
>>> rx_ch  
Characteristic(ch_weight=2.829986944784033003657233894,
    assignment_weights=[1.414993472392016501828616947, 1.414993472392016501828616947, 0, 0, 0],
    input_diff=[0x0000, 0x0000, 0x0000], output_diff=[0x0000, 0x0000, 0x0003],
    assign_outdiff_list=[0x0000, 0x0000, 0x0000, 0x0000, 0x0003])
>>> list(zip(rx_ch.assignment_weights, rx_ch.tuple_assign_outdiff2op_model))  
[(Decimal('1.414993472392016501828616947'), (RXDiff(0x0000), RXModelBvAdd([RXDiff(0x0000), RXDiff(0x0000)]))),
(Decimal('1.414993472392016501828616947'), (RXDiff(0x0000), RXModelBvAdd([RXDiff(0x0000), RXDiff(0x0000)]))),
(Decimal('0'), (RXDiff(0x0000), RXModelId(RXDiff(0x0000)))),
(Decimal('0'), (RXDiff(0x0000), RXModelId(RXDiff(0x0000)))),
(Decimal('0'), (RXDiff(0x0003), RXModelId(RXDiff(0x0003))))]
input_diff

a list of Difference objects containing the (constant) input difference (alias of abstractproperty.characteristic.Characteristic.input_prop).

output_diff

a list of Difference objects containing the (constant) output difference (alias of abstractproperty.characteristic.Characteristic.output_prop).

external_diffs

a list containing the (constant) Difference of the external variables of the function (alias of abstractproperty.characteristic.Characteristic.external_props).

tuple_assign_outdiff2op_model

a tuple where each element is a pair containing: (1) the output (constant) Difference \(\Delta_{x_{i+1}}\) of the non-trivial assignment \(x_{i+1} \leftarrow f_i(x_i)\) and (2) the differential.opmodel.OpModel of this assignment with a (constant) input Difference \(\Delta_{x_{i}}\) (alias of abstractproperty.characteristic.Characteristic.tuple_assign_outprop2op_model).

free_diffs

a list of (symbolic) Difference objects of the Characteristic.ch_model, whose values do not affect the characteristic, and were replaced by constant differences in input_diff, output_diff, external_diffs or tuple_assign_outdiff2op_model (alias of abstractproperty.characteristic.Characteristic.free_props).

var_diff2ct_diff

a collections.OrderedDict mapping each symbolic Difference in the trail to its constant difference (alias of abstractproperty.characteristic.Characteristic.var_prop2ct_prop).

vrepr(ignore_external_diffs=False)[source]

Return an executable string representation.

See also abstractproperty.characteristic.Characteristic.vrepr.

>>> from cascada.bitvector.core import Constant
>>> from cascada.bitvector.operation import RotateLeft
>>> from cascada.differential.difference import XorDiff
>>> from cascada.differential.chmodel import ChModel
>>> from cascada.primitives import speck
>>> Speck32_KS = speck.get_Speck_instance(speck.SpeckInstance.speck_32_64).key_schedule
>>> Speck32_KS.set_num_rounds(2)
>>> xor_ch_model = ChModel(Speck32_KS, XorDiff, ["dmk0", "dmk1", "dmk2"])
>>> zd = core.Constant(0, width=16)
>>> mk0 = RotateLeft(Constant(1, width=16), 5)
>>> aux = RotateLeft(Constant(1, width=16), 14)
>>> xor_ch = Characteristic([mk0, zd, zd], [zd, zd, aux], [zd, aux, zd, zd, aux], xor_ch_model)
>>> xor_ch.vrepr()  
"Characteristic(input_diff=[Constant(0x0020, width=16), Constant(0x0000, width=16), Constant(0x0000, width=16)],
    output_diff=[Constant(0x0000, width=16), Constant(0x0000, width=16), Constant(0x4000, width=16)],
    assign_outdiff_list=[Constant(0x0000, width=16), Constant(0x4000, width=16),
        Constant(0x0000, width=16), Constant(0x0000, width=16), Constant(0x4000, width=16)],
    ch_model=ChModel(func=SpeckKeySchedule.set_num_rounds_and_return(2), diff_type=XorDiff,
        input_diff_names=['dmk0', 'dmk1', 'dmk2'], prefix='dx'))"
>>> xor_ch.srepr()
'Ch(w=1, id=0020 0000 0000, od=0000 0000 4000)'
split(diff_separators)[source]

Split into multiple Characteristic objects given the list of difference separators.

See also abstractproperty.characteristic.Characteristic.split.

>>> from cascada.bitvector.core import Constant, Variable
>>> from cascada.bitvector.operation import RotateLeft
>>> from cascada.differential.difference import XorDiff
>>> from cascada.differential.chmodel import ChModel
>>> from cascada.differential.characteristic import Characteristic
>>> from cascada.primitives import speck
>>> Speck32_KS = speck.get_Speck_instance(speck.SpeckInstance.speck_32_64).key_schedule
>>> Speck32_KS.set_num_rounds(2)
>>> xor_ch_model = ChModel(Speck32_KS, XorDiff, ["dmk0", "dmk1", "dmk2"])
>>> tuple(xor_ch_model.ssa.assignments.items())  
((dx0, dmk1 >>> 7), (dx1, dx0 + dmk2), (dx2, dmk2 <<< 2), (dx3, dx2 ^ dx1),
(dx4, dmk0 >>> 7), (dx5, dx4 + dx3), (dx6, dx5 ^ 0x0001), (dx7, dx3 <<< 2), (dx8, dx7 ^ dx6),
(dmk2_out, Id(dmk2)), (dx3_out, Id(dx3)), (dx8_out, Id(dx8)))
>>> diff_separators = [ (XorDiff(Variable("dx2", width=16)), XorDiff(Variable("dx3", width=16))), ]
>>> zd = core.Constant(0, width=16)
>>> mk0 = RotateLeft(Constant(1, width=16), 5)  # mk0 >>> 7 == 0b010···0
>>> rr2 = RotateLeft(Constant(1, width=16), 14)  # rr2 == 0b010···0 == d5 == d11 (see ch_model)
>>> xor_ch = Characteristic([mk0, zd, zd], [zd, zd, rr2], [zd, rr2, zd, zd, rr2], xor_ch_model)
>>> for ch in xor_ch.split(diff_separators): print(ch)  
Characteristic(ch_weight=0, assignment_weights=[0, 0, 0, 0],
    input_diff=[0x0020, 0x0000, 0x0000], output_diff=[0x0020, 0x0000, 0x0000],
    assign_outdiff_list=[0x0000, 0x0020, 0x0000, 0x0000])
Characteristic(ch_weight=1, assignment_weights=[1, 0, 0, 0],
    input_diff=[0x0020, 0x0000, 0x0000], output_diff=[0x0000, 0x0000, 0x4000],
    assign_outdiff_list=[0x4000, 0x0000, 0x0000, 0x4000])
compute_empirical_ch_weight(num_input_samples=None, num_external_samples=None, split_by_max_weight=None, split_by_rounds=False, seed=None, C_code=False, num_parallel_processes=None)[source]

Compute and store the empirical weight.

The main description of this method can be read from abstractproperty.characteristic.Characteristic.compute_empirical_ch_weight, simply by replacing Property by Difference and input-output pair by differential.

The basic subroutine in this case consists of computing the fraction of right pairs for num_input_samples sampled input pairs. An input pair with difference input_diff is a right pair if output_diff is the difference of the output pair obtained from evaluating the input pair through the underlying bit-vector function.

>>> from cascada.bitvector.core import Constant
>>> from cascada.bitvector.operation import RotateLeft
>>> from cascada.differential.difference import RXDiff
>>> from cascada.differential.chmodel import ChModel
>>> from cascada.differential.characteristic import Characteristic
>>> from cascada.primitives import speck
>>> Speck32_KS = speck.get_Speck_instance(speck.SpeckInstance.speck_32_64).key_schedule
>>> Speck32_KS.set_num_rounds(2)
>>> rx_ch_model = ChModel(Speck32_KS, RXDiff, ["dmk0", "dmk1", "dmk2"])
>>> zd = RXDiff(core.Constant(0, width=16))
>>> td = RXDiff(core.Constant(3, width=16))
>>> rx_ch = Characteristic([zd, zd, zd], [zd, zd, td], [zd, zd, zd, zd, td], rx_ch_model)
>>> rx_ch.compute_empirical_ch_weight(seed=0)
>>> rx_ch.empirical_ch_weight
Decimal('3.033853610869555448012695123')
>>> for data in rx_ch.empirical_data_list: print(data)  
EmpiricalWeightData(weight_avg_aux_prs=3.033853610869555448012695123,
    num_aux_weights=1, num_inf_aux_weights=0, num_input_samples=1466, seed=0, C_code=False)
>>> rx_ch.compute_empirical_ch_weight(seed=0, C_code=True)
>>> rx_ch.empirical_ch_weight
Decimal('2.947813779802864030440499920')
>>> rx_ch.compute_empirical_ch_weight(split_by_max_weight=1.5, seed=0)
>>> rx_ch.empirical_ch_weight
Decimal('2.682204698298087862793386808')
>>> for data in rx_ch.empirical_data_list: print(data)  
EmpiricalWeightData(weight_avg_aux_prs=1.327361980937990421954710722,
    num_aux_weights=1, num_inf_aux_weights=0, num_input_samples=266, seed=0, C_code=False)
EmpiricalWeightData(weight_avg_aux_prs=1.354842717360097440838676086,
    num_aux_weights=1, num_inf_aux_weights=0, num_input_samples=266, seed=0, C_code=False)
classmethod random(ch_model, seed, external_diffs=None)[source]

Return a random Characteristic with given differential.chmodel.ChModel.

See also abstractproperty.characteristic.Characteristic.random.

>>> from cascada.differential.difference import XorDiff
>>> from cascada.differential.chmodel import ChModel
>>> from cascada.differential.characteristic import Characteristic
>>> from cascada.primitives import speck
>>> Speck32_KS = speck.get_Speck_instance(speck.SpeckInstance.speck_32_64).key_schedule
>>> Speck32_KS.set_num_rounds(2)
>>> xor_ch_model = ChModel(Speck32_KS, XorDiff, ["dmk0", "dmk1", "dmk2"])
>>> Characteristic.random(xor_ch_model, 0)  
Characteristic(ch_weight=25, assignment_weights=[13, 12, 0, 0, 0],
    input_diff=[0xc53e, 0xd755, 0x14ba], output_diff=[0x14ba, 0xa6ec, 0x2ce0],
    assign_outdiff_list=[0xf404, 0xb752, 0x14ba, 0xa6ec, 0x2ce0])
class cascada.differential.characteristic.EncryptionCharacteristic(input_diff, output_diff, assign_outdiff_list, ch_model, external_diffs=None, free_diffs=None, empirical_ch_weight=None, empirical_data_list=None, is_valid=True)[source]

Bases: cascada.abstractproperty.characteristic.EncryptionCharacteristic, cascada.differential.characteristic.Characteristic

Represent differential characteristics over encryption functions.

Given a Cipher, an EncryptionCharacteristic is an XOR differential characteristic (see Characteristic) over the Cipher.encryption in the single-key setting (where the Cipher.key_schedule is ignored and round key differences are set to zero).

The propagation probability of an EncryptionCharacteristic is also called in the literature the expected differential probability (EDP) of a characteristic (see https://eprint.iacr.org/2005/212).

>>> from cascada.bitvector.core import Constant
>>> from cascada.bitvector.operation import RotateRight, RotateLeft
>>> from cascada.differential.difference import XorDiff
>>> from cascada.differential.chmodel import EncryptionChModel
>>> from cascada.differential.characteristic import EncryptionCharacteristic
>>> from cascada.primitives import speck
>>> Speck32 = speck.get_Speck_instance(speck.SpeckInstance.speck_32_64)
>>> Speck32.set_num_rounds(2)
>>> ch_model = EncryptionChModel(Speck32, XorDiff)
>>> zd = core.Constant(0, width=16)
>>> rr1 = RotateRight(Constant(1, width=16), 1)  # rr1 == 0b100···0
>>> rr2 = RotateRight(Constant(1, width=16), 2)  # rr2 == 0b010···0
>>> dp0 = RotateLeft(rr1, 7)  # dp0 >>> 7 == rr1
>>> dp1 = rr1
>>> dx6 = Constant(0x0002, width=16)
>>> dx11 = Constant(0x000a, width=16)
>>> ch = EncryptionCharacteristic([dp0, dp1], [dx6, dx11], [zd, dx6, dx6, dx11], ch_model)
>>> ch  
EncryptionCharacteristic(ch_weight=1, assignment_weights=[0, 1, 0, 0],
    input_diff=[0x0040, 0x8000], output_diff=[0x0002, 0x000a], external_diffs=[0x0000, 0x0000],
    assign_outdiff_list=[0x0000, 0x0002, 0x0002, 0x000a])
>>> list(zip(ch.assignment_weights, ch.tuple_assign_outdiff2op_model))  
[(Decimal('0'), (XorDiff(0x0000), XorModelBvAdd([XorDiff(0x8000), XorDiff(0x8000)]))),
(Decimal('1'), (XorDiff(0x0002), XorModelBvAdd([XorDiff(0x0000), XorDiff(0x0002)]))),
(Decimal('0'), (XorDiff(0x0002), XorModelId(XorDiff(0x0002)))),
(Decimal('0'), (XorDiff(0x000a), XorModelId(XorDiff(0x000a))))]
classmethod random(ch_model, seed)[source]

Return a random EncryptionCharacteristic with given differential.chmodel.EncryptionChModel.

The round key differences are set to zero.

See also abstractproperty.characteristic.EncryptionCharacteristic.random.

>>> from cascada.differential.difference import XorDiff
>>> from cascada.differential.chmodel import EncryptionChModel
>>> from cascada.differential.characteristic import EncryptionCharacteristic
>>> from cascada.primitives import speck
>>> Speck32 = speck.get_Speck_instance(speck.SpeckInstance.speck_32_64)
>>> Speck32.set_num_rounds(2)
>>> ch_model = EncryptionChModel(Speck32, XorDiff)
>>> EncryptionCharacteristic.random(ch_model, 0)  
EncryptionCharacteristic(ch_weight=24, assignment_weights=[13, 11, 0, 0],
    input_diff=[0xc53e, 0xd755], output_diff=[0xf43a, 0xc051], external_diffs=[0x0000, 0x0000],
    assign_outdiff_list=[0x904d, 0xf43a, 0xf43a, 0xc051])
class cascada.differential.characteristic.CipherCharacteristic(ks_input_diff, ks_output_diff, ks_assign_outdiff_list, enc_input_diff, enc_output_diff, enc_assign_outdiff_list, cipher_ch_model, ks_free_diffs=None, enc_free_diffs=None, ks_empirical_ch_weight=None, ks_empirical_data_list=None, enc_empirical_ch_weight=None, enc_empirical_data_list=None, ks_is_valid=True, enc_is_valid=True)[source]

Bases: cascada.abstractproperty.characteristic.CipherCharacteristic

Represent related-key differential characteristics over ciphers.

A CipherCharacteristic is a related-key differential characteristic of a block cipher, given by one Characteristic over the Cipher.key_schedule and another Characteristic over the Cipher.encryption.

The related-key setting means that the round key differences in the encryption characteristic (the differences of the external variables of the encryption SSA) are set to the output differences of the key-schedule characteristic.

>>> from cascada.bitvector.core import Constant
>>> from cascada.bitvector.operation import RotateRight, RotateLeft
>>> from cascada.differential.difference import XorDiff, RXDiff
>>> from cascada.differential.chmodel import CipherChModel
>>> from cascada.differential.characteristic import CipherCharacteristic
>>> from cascada.primitives import speck
>>> Speck32 = speck.get_Speck_instance(speck.SpeckInstance.speck_32_64)
>>> Speck32.set_num_rounds(2)
>>> xor_ch_model = CipherChModel(Speck32, XorDiff)
>>> zd = core.Constant(0, width=16)
>>> rr1 = RotateRight(Constant(1, width=16), 1)  # rr1 == 0b100···0
>>> rr2 = RotateRight(Constant(1, width=16), 2)  # rr2 == 0b010···0
>>> mk0 = RotateLeft(Constant(1, width=16), 5)  # mk0 >>> 7 == 0b010···0
>>> dp0 = RotateLeft(rr1, 7)  # dp0 >>> 7 == rr1
>>> dp1 = rr1
>>> dx6 = Constant(0x0002, width=16)
>>> dx11 = Constant(0x000a, width=16)
>>> ch = CipherCharacteristic(
...     [mk0, zd], [zd, rr2], [rr2, zd, rr2],
...     [dp0, dp1], [dx6^rr2, dx11^rr2], [zd, dx6, dx6^rr2, dx11^rr2], xor_ch_model)
>>> ch  
CipherCharacteristic(ks_characteristic=Characteristic(ch_weight=1,
    assignment_weights=[1, 0, 0],
    input_diff=[0x0020, 0x0000], output_diff=[0x0000, 0x4000],
    assign_outdiff_list=[0x4000, 0x0000, 0x4000]),
enc_characteristic=Characteristic(ch_weight=1,
    assignment_weights=[0, 1, 0, 0],
    input_diff=[0x0040, 0x8000], output_diff=[0x4002, 0x400a], external_diffs=[0x0000, 0x4000],
    assign_outdiff_list=[0x0000, 0x0002, 0x4002, 0x400a]))
>>> ks_ch, enc_ch = ch.ks_characteristic, ch.enc_characteristic
>>> list(zip(ks_ch.assignment_weights, ks_ch.tuple_assign_outdiff2op_model))  
[(Decimal('1'), (XorDiff(0x4000), XorModelBvAdd([XorDiff(0x4000), XorDiff(0x0000)]))),
(Decimal('0'), (XorDiff(0x0000), XorModelId(XorDiff(0x0000)))),
(Decimal('0'), (XorDiff(0x4000), XorModelId(XorDiff(0x4000))))]
>>> list(zip(enc_ch.assignment_weights, enc_ch.tuple_assign_outdiff2op_model))  
[(Decimal('0'), (XorDiff(0x0000), XorModelBvAdd([XorDiff(0x8000), XorDiff(0x8000)]))),
(Decimal('1'), (XorDiff(0x0002), XorModelBvAdd([XorDiff(0x0000), XorDiff(0x0002)]))),
(Decimal('0'), (XorDiff(0x4002), XorModelId(XorDiff(0x4002)))),
(Decimal('0'), (XorDiff(0x400a), XorModelId(XorDiff(0x400a))))]
>>> cipher_ch_model = CipherChModel(Speck32, RXDiff)
>>> zd = RXDiff(core.Constant(0, width=16))
>>> ch = CipherCharacteristic(
...     [zd, zd], [zd, zd], [zd, zd, zd],
...     [zd, zd], [zd, zd], [zd, zd, zd, zd], cipher_ch_model)
>>> ch  
CipherCharacteristic(ks_characteristic=Characteristic(ch_weight=1.414993472392016501828616947,
    assignment_weights=[1.414993472392016501828616947, 0, 0],
    input_diff=[0x0000, 0x0000], output_diff=[0x0000, 0x0000],
    assign_outdiff_list=[0x0000, 0x0000, 0x0000]),
enc_characteristic=Characteristic(ch_weight=2.829986944784033003657233894,
    assignment_weights=[1.414993472392016501828616947, 1.414993472392016501828616947, 0, 0],
    input_diff=[0x0000, 0x0000], output_diff=[0x0000, 0x0000], external_diffs=[0x0000, 0x0000],
    assign_outdiff_list=[0x0000, 0x0000, 0x0000, 0x0000]))
>>> ch.srepr()  
'Ch(ks_ch=Ch(w=1.415, id=0000 0000, od=0000 0000), enc_ch=Ch(w=2.830, id=0000 0000, od=0000 0000))'
vrepr()[source]

Return an executable string representation.

See also abstractproperty.characteristic.CipherCharacteristic.vrepr.

>>> from cascada.bitvector.core import Constant
>>> from cascada.bitvector.operation import RotateRight, RotateLeft
>>> from cascada.differential.difference import XorDiff
>>> from cascada.differential.chmodel import CipherChModel
>>> from cascada.differential.characteristic import CipherCharacteristic
>>> from cascada.primitives import speck
>>> Speck32 = speck.get_Speck_instance(speck.SpeckInstance.speck_32_64)
>>> Speck32.set_num_rounds(2)
>>> xor_ch_model = CipherChModel(Speck32, XorDiff)
>>> zd = core.Constant(0, width=16)
>>> rr1 = RotateRight(Constant(1, width=16), 1)  # rr1 == 0b100···0
>>> rr2 = RotateRight(Constant(1, width=16), 2)  # rr2 == 0b010···0
>>> mk0 = RotateLeft(Constant(1, width=16), 5)  # mk0 >>> 7 == 0b010···0
>>> dp0 = RotateLeft(rr1, 7)  # dp0 >>> 7 == rr1
>>> dp1 = rr1
>>> dx6 = Constant(0x0002, width=16)
>>> dx11 = Constant(0x000a, width=16)
>>> ch = CipherCharacteristic(
...     [mk0, zd], [zd, rr2], [rr2, zd, rr2],
...     [dp0, dp1], [dx6^rr2, dx11^rr2], [zd, dx6, dx6^rr2, dx11^rr2], xor_ch_model)
>>> ch.vrepr()  
'CipherCharacteristic(ks_input_diff=[Constant(0x0020, width=16), Constant(0x0000, width=16)],
    ks_output_diff=[Constant(0x0000, width=16), Constant(0x4000, width=16)],
    ks_assign_outdiff_list=[Constant(0x4000, width=16), Constant(0x0000, width=16), Constant(0x4000, width=16)],
    enc_input_diff=[Constant(0x0040, width=16), Constant(0x8000, width=16)],
    enc_output_diff=[Constant(0x4002, width=16), Constant(0x400a, width=16)],
    enc_assign_outdiff_list=[Constant(0x0000, width=16), Constant(0x0002, width=16),
        Constant(0x4002, width=16), Constant(0x400a, width=16)],
    cipher_ch_model=CipherChModel(cipher=SpeckCipher.set_num_rounds_and_return(2), diff_type=XorDiff))'
>>> ch.srepr()
'Ch(ks_ch=Ch(w=1, id=0020 0000, od=0000 4000), enc_ch=Ch(w=1, id=0040 8000, od=4002 400a))'
classmethod random(cipher_ch_model, seed)[source]

Return a random CipherCharacteristic with given differential.chmodel.CipherChModel.

See also abstractproperty.characteristic.CipherCharacteristic.random.

>>> from cascada.differential.difference import XorDiff
>>> from cascada.differential.chmodel import CipherChModel
>>> from cascada.differential.characteristic import CipherCharacteristic
>>> from cascada.primitives import speck
>>> Speck32 = speck.get_Speck_instance(speck.SpeckInstance.speck_32_64)
>>> Speck32.set_num_rounds(2)
>>> xor_ch_model = CipherChModel(Speck32, XorDiff)
>>> CipherCharacteristic.random(xor_ch_model, 0)  
CipherCharacteristic(ks_characteristic=Characteristic(ch_weight=13,
    assignment_weights=[13, 0, 0],
    input_diff=[0xc53e, 0xd755], output_diff=[0xd755, 0xcd1a],
    assign_outdiff_list=[0x904d, 0xd755, 0xcd1a]),
enc_characteristic=Characteristic(ch_weight=24,
    assignment_weights=[11, 13, 0, 0],
    input_diff=[0xfff4, 0xaa87],
    output_diff=[0x4523, 0xb896],
    external_diffs=[0xd755, 0xcd1a],
     assign_outdiff_list=[0x0226, 0x8839, 0x4523, 0xb896]))