cascada.algebraic.characteristic module

Manipulate non-symbolic algebraic characteristics.

Characteristic

Represent algebraic characteristics over bit-vector functions.

EncryptionCharacteristic

Represent algebraic characteristics over encryption functions.

CipherCharacteristic

Represent algebraic characteristics over ciphers.

class cascada.algebraic.characteristic.Characteristic(input_val, output_val, assign_outval_list, ch_model, external_vals=None, free_vals=None, empirical_ch_weight=None, empirical_data_list=None, is_valid=True)[source]

Bases: cascada.abstractproperty.characteristic.Characteristic

Represent algebraic characteristics over bit-vector functions.

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

As mention in abstractproperty.characteristic.Characteristic, the characteristic probability is defined as the product of the propagation probability of the Value pairs \((\Delta_{x_{i}} \mapsto \Delta_{x_{i+1}})\) over \(f_i\). In other words, the characteristic probability is 0 or 1 depending on whether \(f(\Delta_{x_{i+1}}) = \Delta_{x_{i}}\) for all the bit-vector Operation objects \(f_i\) composing the BvFunction \(f\).

Note

Algebraic characteristics only support the default value True for the optional argument is_valid.

>>> from cascada.bitvector.core import Constant
>>> from cascada.bitvector.operation import RotateLeft, RotateRight
>>> from cascada.algebraic.value import BitValue, WordValue
>>> from cascada.algebraic.chmodel import ChModel
>>> from cascada.algebraic.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, BitValue, ["dmk0", "dmk1", "dmk2"])
>>> # assign_outval [vx1, vx5, vmk2_out, vx3_out, vx8_out]
>>> zv = core.Constant(0, width=16)
>>> mk0 = RotateLeft(Constant(1, width=16), 7)  # mk0 >>> 7 == 0b0···01,
>>> x5 = RotateRight(mk0, 7)  # vx5 = mk0 >>> 7
>>> x8 = x5 ^  0x0001 # vx8 = x5 ^ 0x0001
>>> ch = Characteristic([mk0, zv, zv], [zv, zv, x8], [zv, x5, zv, zv, x8], ch_model)
>>> ch  
Characteristic(ch_weight=0, assignment_weights=[0, 0, 0, 0, 0],
    input_val=[0x0080, 0x0000, 0x0000], output_val=[0x0000, 0x0000, 0x0000],
    assign_outval_list=[0x0000, 0x0001, 0x0000, 0x0000, 0x0000])
>>> list(zip(ch.assignment_weights, ch.tuple_assign_outval2op_model))  
[(Decimal('0'), (BitValue(0x0000), BitModelBvAdd([BitValue(0x0000), BitValue(0x0000)]))),
 (Decimal('0'), (BitValue(0x0001), BitModelBvAdd([BitValue(0x0001), BitValue(0x0000)]))),
 (Decimal('0'), (BitValue(0x0000), BitModelId(BitValue(0x0000)))),
 (Decimal('0'), (BitValue(0x0000), BitModelId(BitValue(0x0000)))),
 (Decimal('0'), (BitValue(0x0000), BitModelId(BitValue(0x0000))))]
>>> ch_model = ChModel(Speck32_KS, WordValue, ["vmk0", "vmk1", "vmk2"])
>>> # assign_outval [vmk2_out, vx3_out, vx8_out]
>>> ch = Characteristic([mk0, zv, zv], [zv, zv, x8], [zv, zv, x8], ch_model)
>>> ch  
Characteristic(ch_weight=0, assignment_weights=[0, 0, 0],
    input_val=[0x0080, 0x0000, 0x0000], output_val=[0x0000, 0x0000, 0x0000],
    assign_outval_list=[0x0000, 0x0000, 0x0000])
>>> list(zip(ch.assignment_weights, ch.tuple_assign_outval2op_model))  
[(Decimal('0'), (WordValue(0x0000), WordModelId(WordValue(0x0000)))),
(Decimal('0'), (WordValue(0x0000), WordModelId(WordValue(0x0000)))),
(Decimal('0'), (WordValue(0x0000), WordModelId(WordValue(0x0000))))]
input_val

alias of abstractproperty.characteristic.Characteristic.input_prop.

output_val

alias of abstractproperty.characteristic.Characteristic.output_prop.

external_vals

alias of abstractproperty.characteristic.Characteristic.external_props.

tuple_assign_outval2op_model

alias of abstractproperty.characteristic.Characteristic.tuple_assign_outprop2op_model.

free_vals

alias of abstractproperty.characteristic.Characteristic.free_props.

var_val2ct_val

alias of abstractproperty.characteristic.Characteristic.var_prop2ct_prop.

vrepr(ignore_external_vals=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.algebraic.value import BitValue
>>> from cascada.algebraic.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, BitValue, ["vmk0", "vmk1", "vmk2"])
>>> zv = core.Constant(0, width=16)
>>> mk0 = RotateLeft(Constant(1, width=16), 7)
>>> x5 = RotateRight(mk0, 7)
>>> x8 = x5 ^  0x0001
>>> ch = Characteristic([mk0, zv, zv], [zv, zv, x8], [zv, x5, zv, zv, x8], ch_model)
>>> ch.vrepr()  
"Characteristic(input_val=[Constant(0x0080, width=16), Constant(0x0000, width=16), Constant(0x0000, width=16)],
    output_val=[Constant(0x0000, width=16), Constant(0x0000, width=16), Constant(0x0000, width=16)],
    assign_outval_list=[Constant(0x0000, width=16), Constant(0x0001, width=16),
        Constant(0x0000, width=16), Constant(0x0000, width=16), Constant(0x0000, width=16)],
    ch_model=ChModel(func=SpeckKeySchedule.set_num_rounds_and_return(2), val_type=BitValue,
        input_val_names=['vmk0', 'vmk1', 'vmk2'], prefix='vx'))"
>>> ch.srepr()
'Ch(w=0, id=0080 0000 0000, od=0000 0000 0000)'
split(val_separators)[source]

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

See also abstractproperty.characteristic.Characteristic.split.

>>> from cascada.bitvector.core import Constant, Variable
>>> from cascada.bitvector.operation import RotateLeft, RotateRight
>>> from cascada.algebraic.value import BitValue
>>> from cascada.algebraic.chmodel import ChModel
>>> from cascada.algebraic.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, BitValue, ["vmk0", "vmk1", "vmk2"])
>>> tuple(ch_model.ssa.assignments.items())  
((vx0, vmk1 >>> 7), (vx1, vx0 + vmk2), (vx2, vmk2 <<< 2), (vx3, vx2 ^ vx1),
(vx4, vmk0 >>> 7), (vx5, vx4 + vx3), (vx6, vx5 ^ 0x0001), (vx7, vx3 <<< 2), (vx8, vx7 ^ vx6),
(vmk2_out, Id(vmk2)), (vx3_out, Id(vx3)), (vx8_out, Id(vx8)))
>>> val_separators = [ (BitValue(Variable("vx2", width=16)), BitValue(Variable("vx3", width=16))), ]
>>> zv = core.Constant(0, width=16)
>>> mk0 = RotateLeft(Constant(1, width=16), 7)
>>> x5 = RotateRight(mk0, 7)
>>> x8 = x5 ^  0x0001
>>> ch = Characteristic([mk0, zv, zv], [zv, zv, x8], [zv, x5, zv, zv, x8], ch_model)
>>> for ch in ch.split(val_separators): print(ch)  
Characteristic(ch_weight=0, assignment_weights=[0, 0, 0, 0],
               input_val=[0x0080, 0x0000, 0x0000], output_val=[0x0080, 0x0000, 0x0000],
               assign_outval_list=[0x0000, 0x0080, 0x0000, 0x0000])
Characteristic(ch_weight=0, assignment_weights=[0, 0, 0, 0],
               input_val=[0x0080, 0x0000, 0x0000], output_val=[0x0000, 0x0000, 0x0000],
               assign_outval_list=[0x0001, 0x0000, 0x0000, 0x0000])
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.

This method simply stores ch_weight in empirical_ch_weight and a trivial EmpiricalWeightData object in empirical_data_list.

See also abstractproperty.characteristic.Characteristic.compute_empirical_ch_weight.

classmethod random(ch_model, seed, external_vals=None)[source]

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

See also abstractproperty.characteristic.Characteristic.random.

>>> from cascada.algebraic.value import BitValue
>>> from cascada.algebraic.chmodel import ChModel
>>> from cascada.algebraic.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, BitValue, ["vmk0", "vmk1", "vmk2"])
>>> Characteristic.random(ch_model, 0)  
Characteristic(ch_weight=0, assignment_weights=[0, 0, 0, 0, 0],
    input_val=[0xc53e, 0xd755, 0x14ba], output_val=[0x14ba, 0x9280, 0x5a09],
    assign_outval_list=[0xc068, 0x100a, 0x14ba, 0x9280, 0x5a09])
class cascada.algebraic.characteristic.EncryptionCharacteristic(input_val, output_val, assign_outval_list, ch_model, external_vals=None, free_vals=None, empirical_ch_weight=None, empirical_data_list=None, is_valid=True)[source]

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

Represent algebraic characteristics over encryption functions.

Given a Cipher, an EncryptionCharacteristic is an algebraic characteristic (see Characteristic) over the Cipher.encryption in the single-key setting (where the Cipher.key_schedule is ignored and round key values are given as constant Value).

>>> from cascada.bitvector.core import Constant
>>> from cascada.algebraic.value import BitValue
>>> from cascada.algebraic.chmodel import EncryptionChModel
>>> from cascada.algebraic.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, BitValue)
>>> zv = core.Constant(0, width=16)
>>> vk1 = core.Constant(1, 16)
>>> ch = EncryptionCharacteristic([zv, zv], [vk1, vk1], [zv, zv, vk1, vk1], ch_model, [zv, vk1])
>>> ch  
EncryptionCharacteristic(ch_weight=0, assignment_weights=[0, 0, 0, 0],
    input_val=[0x0000, 0x0000], output_val=[0x0001, 0x0001], external_vals=[0x0000, 0x0001],
    assign_outval_list=[0x0000, 0x0000, 0x0001, 0x0001])
>>> list(zip(ch.assignment_weights, ch.tuple_assign_outval2op_model))  
[(Decimal('0'), (BitValue(0x0000), BitModelBvAdd([BitValue(0x0000), BitValue(0x0000)]))),
 (Decimal('0'), (BitValue(0x0000), BitModelBvAdd([BitValue(0x0000), BitValue(0x0000)]))),
 (Decimal('0'), (BitValue(0x0001), BitModelId(BitValue(0x0001)))),
 (Decimal('0'), (BitValue(0x0001), BitModelId(BitValue(0x0001))))]
classmethod random(ch_model, seed)[source]

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

See also abstractproperty.characteristic.EncryptionCharacteristic.random.

>>> from cascada.algebraic.value import BitValue
>>> from cascada.algebraic.chmodel import EncryptionChModel
>>> from cascada.algebraic.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, BitValue)
>>> EncryptionCharacteristic.random(ch_model, 0)  
EncryptionCharacteristic(ch_weight=0, assignment_weights=[0, 0, 0, 0],
    input_val=[0xc53e, 0xd755], output_val=[0x6322, 0x17ea], external_vals=[0x14ba, 0x8490],
    assign_outval_list=[0x54df, 0xe7b2, 0x6322, 0x17ea])
class cascada.algebraic.characteristic.CipherCharacteristic(ks_input_val, ks_output_val, ks_assign_outval_list, enc_input_val, enc_output_val, enc_assign_outval_list, cipher_ch_model, ks_free_vals=None, enc_free_vals=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 algebraic characteristics over ciphers.

A CipherCharacteristic is given by one algebraic Characteristic over the Cipher.key_schedule and another algebraic Characteristic over the Cipher.encryption, where the round key values in the encryption characteristic (the values of the external variables of the encryption SSA) are set to the output values of the key-schedule characteristic.

>>> from cascada.bitvector.core import Constant
>>> from cascada.bitvector.operation import RotateRight, RotateLeft
>>> from cascada.algebraic.value import BitValue, WordValue
>>> from cascada.algebraic.chmodel import CipherChModel
>>> from cascada.algebraic.characteristic import CipherCharacteristic
>>> from cascada.primitives import speck
>>> Speck32 = speck.get_Speck_instance(speck.SpeckInstance.speck_32_64)
>>> Speck32.set_num_rounds(2)
>>> ch_model = CipherChModel(Speck32, BitValue)
>>> zv = core.Constant(0, width=16)
>>> ch = CipherCharacteristic(
...     [zv, zv], [zv, zv], [zv, zv, zv],
...     [zv, zv], [zv, zv], [zv, zv, zv, zv], ch_model)
>>> ch  
CipherCharacteristic(ks_characteristic=Characteristic(ch_weight=0, assignment_weights=[0, 0, 0],
    input_val=[0x0000, 0x0000], output_val=[0x0000, 0x0000],
    assign_outval_list=[0x0000, 0x0000, 0x0000]),
enc_characteristic=Characteristic(ch_weight=0, assignment_weights=[0, 0, 0, 0],
    input_val=[0x0000, 0x0000], output_val=[0x0000, 0x0000], external_vals=[0x0000, 0x0000],
    assign_outval_list=[0x0000, 0x0000, 0x0000, 0x0000]))
>>> ch.vrepr()  
'CipherCharacteristic(ks_input_val=[Constant(0x0000, width=16), Constant(0x0000, width=16)],
    ks_output_val=[Constant(0x0000, width=16), Constant(0x0000, width=16)],
    ks_assign_outval_list=[Constant(0x0000, width=16), Constant(0x0000, width=16), Constant(0x0000, width=16)],
    enc_input_val=[Constant(0x0000, width=16), Constant(0x0000, width=16)],
    enc_output_val=[Constant(0x0000, width=16), Constant(0x0000, width=16)],
    enc_assign_outval_list=[Constant(0x0000, width=16), Constant(0x0000, width=16), Constant(0x0000, width=16), Constant(0x0000, width=16)],
    cipher_ch_model=CipherChModel(cipher=SpeckCipher.set_num_rounds_and_return(2), val_type=BitValue))'
>>> ks_ch, enc_ch = ch.ks_characteristic, ch.enc_characteristic
>>> list(zip(ks_ch.assignment_weights, ks_ch.tuple_assign_outval2op_model))  
[(Decimal('0'), (BitValue(0x0000), BitModelBvAdd([BitValue(0x0000), BitValue(0x0000)]))),
 (Decimal('0'), (BitValue(0x0000), BitModelId(BitValue(0x0000)))),
 (Decimal('0'), (BitValue(0x0000), BitModelId(BitValue(0x0000))))]
>>> list(zip(enc_ch.assignment_weights, enc_ch.tuple_assign_outval2op_model))  
[(Decimal('0'), (BitValue(0x0000), BitModelBvAdd([BitValue(0x0000), BitValue(0x0000)]))),
 (Decimal('0'), (BitValue(0x0000), BitModelBvAdd([BitValue(0x0000), BitValue(0x0000)]))),
 (Decimal('0'), (BitValue(0x0000), BitModelId(BitValue(0x0000)))),
 (Decimal('0'), (BitValue(0x0000), BitModelId(BitValue(0x0000))))]
>>> cipher_ch_model = CipherChModel(Speck32, WordValue)
>>> ch = CipherCharacteristic(
...     [zv, zv], [zv, zv], [zv, zv, zv],
...     [zv, zv], [zv, zv], [zv, zv, zv, zv], ch_model)
>>> ch  
CipherCharacteristic(ks_characteristic=Characteristic(ch_weight=0, assignment_weights=[0, 0, 0],
    input_val=[0x0000, 0x0000], output_val=[0x0000, 0x0000],
    assign_outval_list=[0x0000, 0x0000, 0x0000]),
enc_characteristic=Characteristic(ch_weight=0, assignment_weights=[0, 0, 0, 0],
    input_val=[0x0000, 0x0000], output_val=[0x0000, 0x0000], external_vals=[0x0000, 0x0000],
    assign_outval_list=[0x0000, 0x0000, 0x0000, 0x0000]))
>>> ch.srepr()  
'Ch(ks_ch=Ch(w=0, id=0000 0000, od=0000 0000), enc_ch=Ch(w=0, id=0000 0000, od=0000 0000))'
classmethod random(cipher_ch_model, seed)[source]

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

See also abstractproperty.characteristic.CipherCharacteristic.random.

>>> from cascada.algebraic.value import WordValue
>>> from cascada.algebraic.chmodel import CipherChModel
>>> from cascada.algebraic.characteristic import CipherCharacteristic
>>> from cascada.primitives import speck
>>> Speck32 = speck.get_Speck_instance(speck.SpeckInstance.speck_32_64)
>>> Speck32.set_num_rounds(2)
>>> ch_model = CipherChModel(Speck32, WordValue)
>>> CipherCharacteristic.random(ch_model, 0)  
CipherCharacteristic(ks_characteristic=Characteristic(ch_weight=0,
    assignment_weights=[0, 0],
    input_val=[0xc53e, 0xd755], output_val=[0xd755, 0x0988],
    assign_outval_list=[0xd755, 0x0988]),
enc_characteristic=Characteristic(ch_weight=0,
    assignment_weights=[0, 0],
    input_val=[0xe53f, 0x11fb], output_val=[0x2b81, 0x2e71], external_vals=[0xd755, 0x0988],
    assign_outval_list=[0x2b81, 0x2e71]))