cascada.linear.characteristic module
Manipulate non-symbolic linear characteristics.
Represent linear characteristics over bit-vector functions.  | 
|
Represent linear characteristics over encryption functions.  | 
- class cascada.linear.characteristic.Characteristic(input_mask, output_mask, assign_outmask_list, ch_model, external_masks=None, free_masks=None, empirical_ch_weight=None, empirical_data_list=None, is_valid=True)[source]
 Bases:
cascada.abstractproperty.characteristic.CharacteristicRepresent linear characteristics over bit-vector functions.
Internally, this class is a subclass of
abstractproperty.characteristic.Characteristic, where thePropertyis aLinearMasktype.As mentioned in
abstractproperty.characteristic.Characteristic, the characteristic probability is defined as the product of the propagation probability (absolute correlation) of theLinearMaskpairs (linear approximations) \((\Delta_{x_{i}} \mapsto \Delta_{x_{i+1}})\) over \(f_i\). If \(f\) has external variables, the characteristic probability approximates the absolute correlation of the input-output mask 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, RotateRight >>> from cascada.linear.mask import LinearMask, LinearMask >>> from cascada.linear.chmodel import ChModel >>> from cascada.linear.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) >>> ch_model = ChModel(Speck32_KS, LinearMask, ["mk0", "mk1", "mk2"]) >>> zm = core.Constant(0, width=16) >>> mk0 = RotateLeft(Constant(1, width=16), 8) # mk0 >>> 7 == 0b0···010 >>> mx5 = RotateRight(mk0, 7) # ~ mk0 >>> 7 == 0b0···010 >>> mx3__1 = RotateRight(Constant(1, width=16), 1) # mx3__1 <<< 2 == 0b0···010 >>> mx3_out = core.Constant(0x8002, 16) >>> assign_outmask_list = [zm, zm, zm, zm, mx5, mx3__1, mx5, mx5, zm, mx3_out, mx5] >>> ch = Characteristic([mk0, zm, zm], [zm, mx3_out, mx5], assign_outmask_list, ch_model) >>> ch Characteristic(ch_weight=1, assignment_weights=[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], input_mask=[0x0100, 0x0000, 0x0000], output_mask=[0x0000, 0x8002, 0x0002], assign_outmask_list=[0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x8000, 0x0002, 0x0002, 0x0000, 0x8002, 0x0002]) >>> list(zip(ch.assignment_weights, ch.tuple_assign_outmask2op_model)) [(Decimal('0'), (LinearMask(0x0000), LinearModelFreeBranch(LinearMask(0x0000)))), (Decimal('0'), (LinearMask(0x0000), LinearModelFreeBranch(LinearMask(0x0000)))), (Decimal('0'), (LinearMask(0x0000), LinearModelBvAdd([LinearMask(0x0000), LinearMask(0x0000)]))), (Decimal('0'), (LinearMask(0x0000), LinearModelBvXor([LinearMask(0x0000), LinearMask(0x0000)]))), (Decimal('0'), (LinearMask(0x0002), LinearModelFreeBranch(LinearMask(0x0000)))), (Decimal('0'), (LinearMask(0x8000), LinearModelFreeBranch(LinearMask(0x0000)))), (Decimal('1'), (LinearMask(0x0002), LinearModelBvAdd([LinearMask(0x0002), LinearMask(0x0002)]))), (Decimal('0'), (LinearMask(0x0002), LinearModelBvXor([LinearMask(0x0002), LinearMask(0x0002)]))), (Decimal('0'), (LinearMask(0x0000), LinearModelId(LinearMask(0x0000)))), (Decimal('0'), (LinearMask(0x8002), LinearModelId(LinearMask(0x8002)))), (Decimal('0'), (LinearMask(0x0002), LinearModelId(LinearMask(0x0002))))]
- input_mask
 a list of
LinearMaskobjects containing the (constant) input mask (alias ofabstractproperty.characteristic.Characteristic.input_prop).
- output_mask
 a list of
LinearMaskobjects containing the (constant) output mask (alias ofabstractproperty.characteristic.Characteristic.output_prop).
- external_masks
 a list containing the (constant)
LinearMaskof the external variables of the function (alias ofabstractproperty.characteristic.Characteristic.external_props).
- tuple_assign_outmask2op_model
 a tuple where each element is a pair containing: (1) the output (constant)
LinearMask\(\Delta_{x_{i+1}}\) of the non-trivial assignment \(x_{i+1} \leftarrow f_i(x_i)\) and (2) thelinear.opmodel.OpModelof this assignment with a (constant) inputLinearMask\(\Delta_{x_{i}}\) (alias ofabstractproperty.characteristic.Characteristic.tuple_assign_outprop2op_model).
- free_masks
 a list of (symbolic)
LinearMaskobjects of theCharacteristic.ch_model, whose values do not affect the characteristic, and were replaced by constant masks ininput_mask,output_mask,external_masksortuple_assign_outmask2op_model(alias ofabstractproperty.characteristic.Characteristic.free_props).
- var_mask2ct_mask
 a
collections.OrderedDictmapping each symbolicLinearMaskin the trail to its constant mask (alias ofabstractproperty.characteristic.Characteristic.var_prop2ct_prop).
- vrepr(ignore_external_masks=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, RotateRight >>> from cascada.linear.mask import LinearMask >>> from cascada.linear.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) >>> ch_model = ChModel(Speck32_KS, LinearMask, ["mk0", "mk1", "mk2"]) >>> zm = core.Constant(0, width=16) >>> mk0 = RotateLeft(Constant(1, width=16), 8) # mk0 >>> 7 == 0b0···010 >>> mx5 = RotateRight(mk0, 7) # ~ mk0 >>> 7 == 0b0···010 >>> mx3__1 = RotateRight(Constant(1, width=16), 1) # mx3__1 <<< 2 == 0b0···010 >>> mx3_out = core.Constant(0x8002, 16) >>> assign_outmask_list = [zm, zm, zm, zm, mx5, mx3__1, mx5, mx5, zm, mx3_out, mx5] >>> ch = Characteristic([mk0, zm, zm], [zm, mx3_out, mx5], assign_outmask_list, ch_model) >>> ch.vrepr() "Characteristic(input_mask=[Constant(0x0100, width=16), Constant(0x0000, width=16), Constant(0x0000, width=16)], output_mask=[Constant(0x0000, width=16), Constant(0x8002, width=16), Constant(0x0002, width=16)], assign_outmask_list=[Constant(0x0000, width=16), Constant(0x0000, width=16), Constant(0x0000, width=16), Constant(0x0000, width=16), Constant(0x0002, width=16), Constant(0x8000, width=16), Constant(0x0002, width=16), Constant(0x0002, width=16), Constant(0x0000, width=16), Constant(0x8002, width=16), Constant(0x0002, width=16)], ch_model=ChModel(func=SpeckKeySchedule.set_num_rounds_and_return(2), mask_type=LinearMask, input_mask_names=['mk0', 'mk1', 'mk2'], prefix='mx'))" >>> ch.srepr() 'Ch(w=1, id=0100 0000 0000, od=0000 8002 0002)'
- split(mask_separators)[source]
 Split into multiple
Characteristicobjects given the list of mask separators.See also
abstractproperty.characteristic.Characteristic.split.>>> from cascada.bitvector.core import Constant, Variable >>> from cascada.bitvector.operation import RotateLeft, RotateRight >>> from cascada.linear.mask import LinearMask >>> from cascada.linear.chmodel import ChModel >>> from cascada.linear.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) >>> ch_model = ChModel(Speck32_KS, LinearMask, ["mk0", "mk1", "mk2"]) >>> tuple(ch_model.ssa.assignments.items()) ((mx0, mk1 >>> 7), (mk2__0, Id(mk2)), (mk2__1, Id(mk2)), (mk2__2, Id(mk2)), (mx1, mx0 + mk2__0), (mx2, mk2__1 <<< 2), (mx3, mx2 ^ mx1), (mx4, mk0 >>> 7), (mx3__0, Id(mx3)), (mx3__1, Id(mx3)), (mx3__2, Id(mx3)), (mx5, mx4 + mx3__0), (mx6, mx5 ^ 0x0001), (mx7, mx3__1 <<< 2), (mx8, mx7 ^ mx6), (mk2_out, Id(mk2__2)), (mx3_out, Id(mx3__2)), (mx8_out, Id(mx8))) >>> mask_separators = [ (LinearMask(Variable("mx2", width=16)), LinearMask(Variable("mx3", width=16))), ] >>> zm = core.Constant(0, width=16) >>> mk0 = RotateLeft(Constant(1, width=16), 8) # mk0 >>> 7 == 0b0···010 >>> mx5 = RotateRight(mk0, 7) # ~ mk0 >>> 7 == 0b0···010 >>> mx3__1 = RotateRight(Constant(1, width=16), 1) # mx3__1 <<< 2 == 0b0···010 >>> mx3_out = core.Constant(0x8002, 16) >>> assign_outmask_list = [zm, zm, zm, zm, mx5, mx3__1, mx5, mx5, zm, mx3_out, mx5] >>> ch = Characteristic([mk0, zm, zm], [zm, mx3_out, mx5], assign_outmask_list, ch_model) >>> for ch in ch.split(mask_separators): print(ch) Characteristic(ch_weight=0, assignment_weights=[0, 0, 0, 0, 0, 0, 0], input_mask=[0x0100, 0x0000, 0x0000], output_mask=[0x0100, 0x0000, 0x0000], assign_outmask_list=[0x0000, 0x0000, 0x0000, 0x0000, 0x0100, 0x0000, 0x0000]) Characteristic(ch_weight=1, assignment_weights=[0, 0, 1, 0, 0, 0, 0], input_mask=[0x0100, 0x0000, 0x0000], output_mask=[0x0000, 0x8002, 0x0002], assign_outmask_list=[0x0002, 0x8000, 0x0002, 0x0002, 0x0000, 0x8002, 0x0002])
- classmethod random(ch_model, seed, external_masks=None)[source]
 Return a random
Characteristicwith givenlinear.chmodel.ChModel.See also
abstractproperty.characteristic.Characteristic.random.>>> from cascada.linear.mask import LinearMask >>> from cascada.linear.chmodel import ChModel >>> from cascada.linear.characteristic import Characteristic >>> from cascada.bitvector.ssa import BvFunction >>> class MyFoo(BvFunction): ... input_widths, output_widths = [4, 4], [4, 4] ... @classmethod ... def eval(cls, a, b): return a + b, a >>> ch_model = ChModel(MyFoo, LinearMask, ["ma", "mb"]) >>> Characteristic.random(ch_model, 0) Characteristic(ch_weight=2, assignment_weights=[0, 2, 0, 0], input_mask=[0x2, 0x6], output_mask=[0x4, 0x5], assign_outmask_list=[0x7, 0x4, 0x4, 0x5])
- 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 replacingPropertybyLinearMaskand input-output pair by hull.The basic subroutine in this case consists of computing the fraction of right inputs for
num_input_samplessampled inputs. An input \(x\) is a right input if \(\langle \alpha, x \rangle = \langle \beta, f(x) \rangle\), where \(\alpha\) isinput_mask, \(\beta\) isoutput_maskand \(f\) is the underlying bit-vector function.>>> from cascada.bitvector.core import Constant >>> from cascada.bitvector.operation import RotateLeft, RotateRight >>> from cascada.linear.mask import LinearMask, LinearMask >>> from cascada.linear.chmodel import ChModel >>> from cascada.linear.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) >>> ch_model = ChModel(Speck32_KS, LinearMask, ["mk0", "mk1", "mk2"]) >>> zm = core.Constant(0, width=16) >>> mk0 = RotateLeft(Constant(1, width=16), 8) # mk0 >>> 7 == 0b0···010 >>> mx5 = RotateRight(mk0, 7) # ~ mk0 >>> 7 == 0b0···010 >>> mx3__1 = RotateRight(Constant(1, width=16), 1) # mx3__1 <<< 2 == 0b0···010 >>> mx3_out = core.Constant(0x8002, 16) >>> assign_outmask_list = [zm, zm, zm, zm, mx5, mx3__1, mx5, mx5, zm, mx3_out, mx5] >>> ch = Characteristic([mk0, zm, zm], [zm, mx3_out, mx5], assign_outmask_list, ch_model) >>> ch.compute_empirical_ch_weight(seed=0) >>> ch.empirical_ch_weight Decimal('1.093109404391481470675941626') >>> for data in ch.empirical_data_list: print(data) EmpiricalWeightData(weight_avg_aux_prs=1.093109404391481470675941626, num_aux_weights=1, num_inf_aux_weights=0, num_input_samples=192, seed=0, C_code=False) >>> ch.compute_empirical_ch_weight(seed=0, C_code=True) >>> ch.empirical_ch_weight Decimal('1.061400544664143309159590699')
- class cascada.linear.characteristic.EncryptionCharacteristic(input_mask, output_mask, assign_outmask_list, ch_model, external_masks=None, free_masks=None, empirical_ch_weight=None, empirical_data_list=None, is_valid=True)[source]
 Bases:
cascada.abstractproperty.characteristic.EncryptionCharacteristic,cascada.linear.characteristic.CharacteristicRepresent linear characteristics over encryption functions.
Given a
Cipher, anEncryptionCharacteristicis a linear characteristic (seeCharacteristic) over theCipher.encryption(where theCipher.key_scheduleis ignored and round key masks are given as constantLinearMask).The propagation probability of an
EncryptionCharacteristicis similar to the expected linear probability (ELP), but instead of multiplying the absolute correlations, the ELP multiplies the square of the correlations (see https://eprint.iacr.org/2005/212).>>> from cascada.bitvector.core import Constant >>> from cascada.bitvector.operation import RotateRight, RotateLeft >>> from cascada.linear.mask import LinearMask >>> from cascada.linear.chmodel import EncryptionChModel >>> from cascada.linear.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, LinearMask) >>> zm = core.Constant(0, width=16) >>> p1 = core.Constant(0x0600, width=16) >>> c0 = core.Constant(0x60f0, width=16) >>> c1 = core.Constant(0x60c0, width=16) >>> k1 = core.Constant(0x0030, width=16) >>> bv_1800 = core.Constant(0x1800, width=16) >>> assign_outmask_list = [zm, zm, zm, bv_1800, bv_1800, k1, k1, k1, c1, c1, c0, c1] >>> ch = EncryptionCharacteristic([zm, p1], [c0, c1], assign_outmask_list, ch_model, [zm, k1]) >>> ch EncryptionCharacteristic(ch_weight=1, assignment_weights=[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], input_mask=[0x0000, 0x0600], output_mask=[0x60f0, 0x60c0], external_masks=[0x0000, 0x0030], assign_outmask_list=[0x0000, 0x0000, 0x0000, 0x1800, 0x1800, 0x0030, 0x0030, 0x0030, 0x60c0, 0x60c0, 0x60f0, 0x60c0]) >>> list(zip(ch.assignment_weights, ch.tuple_assign_outmask2op_model)) [(Decimal('0'), (LinearMask(0x0000), LinearModelFreeBranch(LinearMask(0x0600)))), (Decimal('0'), (LinearMask(0x0000), LinearModelBvAdd([LinearMask(0x0000), LinearMask(0x0000)]))), (Decimal('0'), (LinearMask(0x0000), LinearModelBvXor([LinearMask(0x0000), LinearMask(0x0000)]))), (Decimal('0'), (LinearMask(0x1800), LinearModelFreeBranch(LinearMask(0x0000)))), (Decimal('0'), (LinearMask(0x1800), LinearModelBvXor([LinearMask(0x1800), LinearMask(0x1800)]))), (Decimal('0'), (LinearMask(0x0030), LinearModelFreeBranch(LinearMask(0x1800)))), (Decimal('1'), (LinearMask(0x0030), LinearModelBvAdd([LinearMask(0x0030), LinearMask(0x0030)]))), (Decimal('0'), (LinearMask(0x0030), LinearModelBvXor([LinearMask(0x0030), LinearMask(0x0030)]))), (Decimal('0'), (LinearMask(0x60c0), LinearModelFreeBranch(LinearMask(0x0030)))), (Decimal('0'), (LinearMask(0x60c0), LinearModelBvXor([LinearMask(0x60c0), LinearMask(0x60c0)]))), (Decimal('0'), (LinearMask(0x60f0), LinearModelId(LinearMask(0x60f0)))), (Decimal('0'), (LinearMask(0x60c0), LinearModelId(LinearMask(0x60c0))))]