cascada.differential.chmodel module

Manage bit-vector models of differential characteristics.

ChModel

Represent bit-vector models of differential characteristics over bit-vector functions.

EncryptionChModel

Represent differential characteristic models of encryption functions.

CipherChModel

Represent related-key differential characteristic models of ciphers.

class cascada.differential.chmodel.ChModel(func, diff_type, input_diff_names, prefix='dx', external_var2diff=None, op_model_class2options=None)[source]

Bases: cascada.abstractproperty.chmodel.ChModel

Represent bit-vector models of differential characteristics over bit-vector functions.

Internally, this class is a subclass of abstractproperty.chmodel.ChModel, where the Property is a Difference type and the probability of the characteristic here considered is the product of the probabilities of the differentials \((\Delta_{x_{i}} \mapsto \Delta_{x_{i+1}})\) composing the characteristic (see differential.characteristic.Characteristic).

If the SSA of the BvFunction contains external Variable objects and their Difference objects are not provided in the initialization through external_var2diff, these free external differences are set to zero when the argument diff_type is XorDiff.

Note

Free external differences are not supported by ChModel when diff_type is RXDiff. For this type of difference, all external differences must be provided in external_var2diff.

>>> from cascada.bitvector.core import Variable
>>> from cascada.differential.difference import XorDiff, RXDiff
>>> 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"])
>>> xor_ch_model  
ChModel(func=SpeckKeySchedule_2R,
    input_diff=[XorDiff(dmk0), XorDiff(dmk1), XorDiff(dmk2)],
    output_diff=[XorDiff(dmk2_out), XorDiff(dx3_out), XorDiff(dx8_out)],
    assign_outdiff2op_model=[(XorDiff(dx1), XorModelBvAdd([XorDiff(dmk1 >>> 7), XorDiff(dmk2)])),
        (XorDiff(dx5), XorModelBvAdd([XorDiff(dmk0 >>> 7), XorDiff((dmk2 <<< 2) ^ dx1)])),
        (XorDiff(dmk2_out), XorModelId(XorDiff(dmk2))),
        (XorDiff(dx3_out), XorModelId(XorDiff((dmk2 <<< 2) ^ dx1))),
        (XorDiff(dx8_out), XorModelId(XorDiff((((dmk2 <<< 2) ^ dx1) <<< 2) ^ dx5)))])
>>> xor_ch_model.ssa  
SSA(input_vars=[dmk0, dmk1, dmk2],
    output_vars=[dmk2_out, dx3_out, dx8_out],
    assignments=[(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))])
>>> rx_ch_model = ChModel(Speck32_KS, RXDiff, ["dmk0", "dmk1", "dmk2"])
>>> rx_ch_model  
ChModel(func=SpeckKeySchedule_2R,
        input_diff=[RXDiff(dmk0), RXDiff(dmk1), RXDiff(dmk2)],
        output_diff=[RXDiff(dmk2_out), RXDiff(dx3_out), RXDiff(dx8_out)],
        assign_outdiff2op_model=[(RXDiff(dx1), RXModelBvAdd([RXDiff(dmk1 >>> 7), RXDiff(dmk2)])),
            (RXDiff(dx5), RXModelBvAdd([RXDiff(dmk0 >>> 7), RXDiff((dmk2 <<< 2) ^ dx1)])),
            (RXDiff(dmk2_out), RXModelId(RXDiff(dmk2))),
            (RXDiff(dx3_out), RXModelId(RXDiff((dmk2 <<< 2) ^ dx1))),
            (RXDiff(dx8_out), RXModelId(RXDiff((((dmk2 <<< 2) ^ dx1) <<< 2) ^ dx5 ^ 0x0003)))])
diff_type

the type of Difference of the characteristic (alias of abstractproperty.chmodel.ChModel.prop_type).

input_diff

a list of Difference objects containing the (symbolic) input difference (alias of abstractproperty.chmodel.ChModel.input_prop).

output_diff

a list of Difference objects containing the (symbolic) output difference (alias of abstractproperty.chmodel.ChModel.output_prop).

external_var2diff

a collections.OrderedDict mapping the external variables of abstractproperty.chmodel.ChModel.ssa to their associated (symbolic or constant) Difference objects (alias of abstractproperty.chmodel.ChModel.external_var2prop).

assign_outdiff2op_model

a collections.OrderedDict mapping the output Difference \(\Delta_{x_{i+1}}\) of the non-trivial assignment \(x_{i+1} \leftarrow f_i(x_i)\) to the differential.opmodel.OpModel of this assignment (alias of abstractproperty.chmodel.ChModel.assign_outprop2op_model).

var2diff

a collections.OrderedDict mapping each variable in abstractproperty.chmodel.ChModel.ssa to its associated Difference object (alias of abstractproperty.chmodel.ChModel.var2prop).

vrepr()[source]

Return an executable string representation.

See also abstractproperty.chmodel.ChModel.vrepr.

>>> from cascada.bitvector.core import Variable
>>> 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)
>>> ch_model = ChModel(Speck32_KS, XorDiff, ["dmk0", "dmk1", "dmk2"])
>>> ch_model.vrepr()  
"ChModel(func=SpeckKeySchedule.set_num_rounds_and_return(2), diff_type=XorDiff,
         input_diff_names=['dmk0', 'dmk1', 'dmk2'], prefix='dx')"
validity_assertions()[source]

Return the validity constraint as a list of assertions.

See also abstractproperty.chmodel.ChModel.validity_assertions.

>>> from functools import reduce
>>> from cascada.bitvector.core import Variable
>>> from cascada.bitvector.operation import BvAnd
>>> 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"])
>>> assertions = xor_ch_model.validity_assertions()
>>> for a in assertions: print(a)  
((~((dmk1 >>> 7) << 0x0001) ^ (dmk2 << 0x0001)) & (~((dmk1 >>> 7) << 0x0001) ^ (dx1 << 0x0001)) &
    ((dmk1 >>> 7) ^ dmk2 ^ dx1 ^ ((dmk1 >>> 7) << 0x0001))) == 0x0000
((~((dmk0 >>> 7) << 0x0001) ^ (((dmk2 <<< 2) ^ dx1) << 0x0001)) & (~((dmk0 >>> 7) << 0x0001) ^
    (dx5 << 0x0001)) & ((dmk0 >>> 7) ^ (dmk2 <<< 2) ^ dx1 ^ dx5 ^ ((dmk0 >>> 7) << 0x0001))) == 0x0000
dmk2 == dmk2_out
((dmk2 <<< 2) ^ dx1) == dx3_out
((((dmk2 <<< 2) ^ dx1) <<< 2) ^ dx5) == dx8_out
>>> validity_constraint = reduce(BvAnd, assertions)
>>> validity_constraint  
(((~((dmk1 >>> 7) << 0x0001) ^ (dmk2 << 0x0001)) & ...
pr_one_assertions()[source]

Return the probability-one constraint as a list of assertions.

See also abstractproperty.chmodel.ChModel.pr_one_assertions.

>>> from cascada.bitvector.core import Variable
>>> 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"])
>>> for a in xor_ch_model.pr_one_assertions(): print(a)  
(((~((dmk1 >>> 7) << 0x0001) ^ (dmk2 << 0x0001)) & (~((dmk1 >>> 7) << 0x0001) ^ (dx1 << 0x0001)) &
    ((dmk1 >>> 7) ^ dmk2 ^ dx1 ^ ((dmk1 >>> 7) << 0x0001))) == 0x0000) & ((~((~(dmk1 >>> 7) ^ dmk2) &
    (~(dmk1 >>> 7) ^ dx1))[14:]) == 0b000000000000000)
(((~((dmk0 >>> 7) << 0x0001) ^ (((dmk2 <<< 2) ^ dx1) << 0x0001)) & (~((dmk0 >>> 7) << 0x0001) ^
    (dx5 << 0x0001)) & ((dmk0 >>> 7) ^ (dmk2 <<< 2) ^ dx1 ^ dx5 ^ ((dmk0 >>> 7) << 0x0001))) == 0x0000) &
    ((~((~(dmk0 >>> 7) ^ (dmk2 <<< 2) ^ dx1) & (~(dmk0 >>> 7) ^ dx5))[14:]) == 0b000000000000000)
dmk2 == dmk2_out
((dmk2 <<< 2) ^ dx1) == dx3_out
((((dmk2 <<< 2) ^ dx1) <<< 2) ^ dx5) == dx8_out
weight_assertions(ch_weight_variable, assign_weight_variables, truncate=True)[source]

Return the weight constraint as a list of assertions.

See also abstractproperty.chmodel.ChModel.weight_assertions.

>>> from cascada.bitvector.core import Variable
>>> from cascada.differential.difference import XorDiff, RXDiff
>>> 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)
>>> cm = ChModel(Speck32_KS, XorDiff, ["dmk0", "dmk1", "dmk2"])
>>> cwv = Variable("w", cm.weight_width())
>>> omvs = [Variable(f"w{i}", om.weight_width()) for i, om in enumerate(cm.assign_outdiff2op_model.values())]
>>> for a in cm.weight_assertions(cwv, omvs): print(a)  
w0 == PopCount(~((~(dmk1 >>> 7) ^ dmk2) & (~(dmk1 >>> 7) ^ dx1))[14:])
w1 == PopCount(~((~(dmk0 >>> 7) ^ (dmk2 <<< 2) ^ dx1) & (~(dmk0 >>> 7) ^ dx5))[14:])
w2 == 0b0
w3 == 0b0
w4 == 0b0
w == ((0b0 :: w0) + (0b0 :: w1))
>>> cm = ChModel(Speck32_KS, RXDiff, ["dmk0", "dmk1", "dmk2"])  # RXDiff for the fb
>>> cwv = Variable("w", cm.weight_width())
>>> omvs = [Variable(f"w{i}", om.weight_width()) for i, om in enumerate(cm.assign_outdiff2op_model.values())]
>>> for a in cm.weight_assertions(cwv, omvs): print(a)  
w0 == (((0x0 :: PopCount(((((dmk1 >>> 7)[:1]) ^ (dx1[:1])) | ((dmk2[:1]) ^ (dx1[:1])))[13:])) << 0x03) +
    (Ite(~((dmk1[8]) ^ (dmk2[1]) ^ (dx1[1])), 0x0b, 0x18)))
w1 == (((0x0 :: PopCount(((((dmk0 >>> 7)[:1]) ^ (dx5[:1])) | ((((dmk2 <<< 2) ^ dx1)[:1]) ^
    (dx5[:1])))[13:])) << 0x03) + (Ite(~((dmk0[8]) ^ (((dmk2 <<< 2) ^ dx1)[1]) ^ (dx5[1])), 0x0b, 0x18)))
w2 == 0b0
w3 == 0b0
w4 == 0b0
w == (((0b0 :: w0) + (0b0 :: w1))[:3])
max_weight(truncate=True)[source]

Return the maximum value the ch. weight variable can achieve in weight_assertions.

See also abstractproperty.chmodel.ChModel.max_weight.

>>> from cascada.bitvector.core import Variable
>>> from cascada.differential.difference import XorDiff, RXDiff
>>> 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_cm = ChModel(Speck32_KS, XorDiff, ["dmk0", "dmk1", "dmk2"])
>>> xor_cm.max_weight(), xor_cm.weight_width(), xor_cm.num_frac_bits()
(30, 5, 0)
>>> rx_cm = ChModel(Speck32_KS, RXDiff, ["dmk0", "dmk1", "dmk2"])
>>> rx_cm.num_frac_bits()
3
>>> rx_cm.max_weight(), rx_cm.weight_width()
(34, 6)
>>> rx_cm.max_weight(truncate=False), rx_cm.weight_width(truncate=False)
(272, 9)
error()[source]

Return the maximum difference between weight_assertions and the exact weight.

See also abstractproperty.chmodel.ChModel.error.

>>> from cascada.bitvector.core import Variable
>>> from cascada.differential.difference import XorDiff, RXDiff
>>> from cascada.differential.opmodel import RXModelBvAdd
>>> 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)
>>> ChModel(Speck32_KS, XorDiff, ["dmk0", "dmk1", "dmk2"]).error()
0
>>> ChModel(Speck32_KS, RXDiff, ["dmk0", "dmk1", "dmk2"]).error()
Decimal('2.102441455630541244332995062')
>>> opt = {RXModelBvAdd: {"precision": 0}}
>>> ChModel(Speck32_KS, RXDiff, ["dmk0", "dmk1", "dmk2"], op_model_class2options=opt).error()
Decimal('2.852441455630541244332995062')
signature(sig_type)[source]

Return the signature of the characteristic model.

See also abstractproperty.chmodel.ChModel.signature.

>>> from cascada.bitvector.core import Variable
>>> from cascada.differential.difference import XorDiff
>>> from cascada.differential.chmodel import ChModel, ChModelSigType
>>> 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, XorDiff, ["dmk0", "dmk1", "dmk2"])
>>> ch_model.signature(ChModelSigType.Unique)
[dmk0, dmk1, dmk2, dx1, dx5]
>>> ch_model.signature(ChModelSigType.InputOutput)
[dmk0, dmk1, dmk2, dmk2_out, dx3_out, dx8_out]
split(diff_separators)[source]

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

See also abstractproperty.chmodel.ChModel.split.

>>> from cascada.bitvector.core import Variable
>>> from cascada.differential.difference import XorDiff
>>> from cascada.differential.chmodel import ChModel, ChModelSigType
>>> 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, XorDiff, ["dmk0", "dmk1", "dmk2"])
>>> tuple(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))), ]
>>> for cm in ch_model.split(diff_separators): print(cm)  
ChModel(func=SpeckKeySchedule_2R_0S,
        input_diff=[XorDiff(dmk0), XorDiff(dmk1), XorDiff(dmk2)],
        output_diff=[XorDiff(dmk0_out), XorDiff(dx3_out), XorDiff(dmk2_out)],
        assign_outdiff2op_model=[(XorDiff(dx1), XorModelBvAdd([XorDiff(dmk1 >>> 7), XorDiff(dmk2)])),
            (XorDiff(dmk0_out), XorModelId(XorDiff(dmk0))),
            (XorDiff(dx3_out), XorModelId(XorDiff((dmk2 <<< 2) ^ dx1))),
            (XorDiff(dmk2_out), XorModelId(XorDiff(dmk2)))])
ChModel(func=SpeckKeySchedule_2R_1S,
        input_diff=[XorDiff(dmk0), XorDiff(dx3), XorDiff(dmk2)],
        output_diff=[XorDiff(dmk2_out), XorDiff(dx3_out), XorDiff(dx8_out)],
        assign_outdiff2op_model=[(XorDiff(dx5), XorModelBvAdd([XorDiff(dmk0 >>> 7), XorDiff(dx3)])),
            (XorDiff(dmk2_out), XorModelId(XorDiff(dmk2))),
            (XorDiff(dx3_out), XorModelId(XorDiff(dx3))),
            (XorDiff(dx8_out), XorModelId(XorDiff((dx3 <<< 2) ^ dx5)))])
get_round_separators()[source]

Return the round separators if func is a RoundBasedFunction.

See also abstractproperty.chmodel.ChModel.get_round_separators.

>>> 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)
>>> ch_model = ChModel(Speck32_KS, XorDiff, ["dmk0", "dmk1", "dmk2"])
>>> sub_cms = ch_model.split(ch_model.get_round_separators())
>>> for cm in sub_cms: print(cm)  
ChModel(func=SpeckKeySchedule_2R_0S,
        input_diff=[XorDiff(dmk0), XorDiff(dmk1), XorDiff(dmk2)],
        output_diff=[XorDiff(dmk0_out), XorDiff(dx3_out), XorDiff(dmk2_out)],
        assign_outdiff2op_model=[(XorDiff(dx1), XorModelBvAdd([XorDiff(dmk1 >>> 7), XorDiff(dmk2)])),
            (XorDiff(dmk0_out), XorModelId(XorDiff(dmk0))),
            (XorDiff(dx3_out), XorModelId(XorDiff((dmk2 <<< 2) ^ dx1))),
            (XorDiff(dmk2_out), XorModelId(XorDiff(dmk2)))])
ChModel(func=SpeckKeySchedule_2R_1S,
        input_diff=[XorDiff(dmk0), XorDiff(dx3), XorDiff(dmk2)],
        output_diff=[XorDiff(dmk2_out), XorDiff(dx3_out), XorDiff(dx8_out)],
        assign_outdiff2op_model=[(XorDiff(dx5), XorModelBvAdd([XorDiff(dmk0 >>> 7), XorDiff(dx3)])),
            (XorDiff(dmk2_out), XorModelId(XorDiff(dmk2))),
            (XorDiff(dx3_out), XorModelId(XorDiff(dx3))),
            (XorDiff(dx8_out), XorModelId(XorDiff((dx3 <<< 2) ^ dx5)))])
class cascada.differential.chmodel.EncryptionChModel(cipher, diff_type, op_model_class2options=None)[source]

Bases: cascada.abstractproperty.chmodel.EncryptionChModel, cascada.differential.chmodel.ChModel

Represent differential characteristic models of encryption functions.

Given a Cipher, an EncryptionChModel is a bit-vector model (see ChModel) of a differential 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).

Note

EncryptionChModel only supports XorDiff for diff_type (and not RXDiff).

See also differential.characteristic.EncryptionCharacteristic.

In an EncryptionChModel, the plaintext differences start with the prefix "dp", the intermediate and output differences start with the prefix "dx", and the round key differences (the differences of the external variables of the encryption SSA) start with the prefix "dk".

>>> from cascada.bitvector.core import Variable
>>> from cascada.differential.difference import XorDiff
>>> from cascada.differential.chmodel import EncryptionChModel
>>> 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)
>>> ch_model  
EncryptionChModel(cipher=SpeckCipher_2R, input_diff=[XorDiff(dp0), XorDiff(dp1)],
    output_diff=[XorDiff(dx7_out), XorDiff(dx9_out)],
    external_var2diff=[(dk0, XorDiff(0x0000)), (dk1, XorDiff(0x0000))],
    assign_outdiff2op_model=[(XorDiff(dx1), XorModelBvAdd([XorDiff(dp0 >>> 7), XorDiff(dp1)])),
        (XorDiff(dx6), XorModelBvAdd([XorDiff(dx1 >>> 7), XorDiff((dp1 <<< 2) ^ dx1)])),
        (XorDiff(dx7_out), XorModelId(XorDiff(dx6))),
        (XorDiff(dx9_out), XorModelId(XorDiff((((dp1 <<< 2) ^ dx1) <<< 2) ^ dx6)))])
>>> ch_model.ssa  
SSA(input_vars=[dp0, dp1], output_vars=[dx7_out, dx9_out], external_vars=[dk0, dk1],
    assignments=[(dx0, dp0 >>> 7), (dx1, dx0 + dp1), (dx2, dx1 ^ dk0), (dx3, dp1 <<< 2),
        (dx4, dx3 ^ dx2), (dx5, dx2 >>> 7), (dx6, dx5 + dx4), (dx7, dx6 ^ dk1),
        (dx8, dx4 <<< 2), (dx9, dx8 ^ dx7), (dx7_out, Id(dx7)), (dx9_out, Id(dx9))])
vrepr()[source]

Return an executable string representation.

See also abstractproperty.chmodel.EncryptionChModel.vrepr.

>>> from cascada.bitvector.core import Variable
>>> from cascada.differential.difference import XorDiff
>>> from cascada.differential.chmodel import EncryptionChModel
>>> from cascada.primitives import speck
>>> Speck32 = speck.get_Speck_instance(speck.SpeckInstance.speck_32_64)
>>> Speck32.set_num_rounds(2)
>>> EncryptionChModel(Speck32, XorDiff).vrepr()
'EncryptionChModel(cipher=SpeckCipher.set_num_rounds_and_return(2), diff_type=XorDiff)'
class cascada.differential.chmodel.CipherChModel(cipher, diff_type, op_model_class2options=None)[source]

Bases: cascada.abstractproperty.chmodel.CipherChModel

Represent related-key differential characteristic models of ciphers.

Given a Cipher, a CipherChModel is a bit-vector model of a related-key differential characteristic (see differential.characteristic.CipherCharacteristic) over the cipher.

A CipherChModel consists of a pair of ChModel where one models the characteristic over the Cipher.key_schedule, and the other one models the characteristic over the Cipher.encryption.

In a CipherChModel, the master key differences start with the prefix "dmk", the intermediate and output differences of the key schedule start with the prefix "dk", the plaintext differences start with the prefix "dp" and intermediate and output differences of the encryption with the prefix "dx".

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 Variable
>>> from cascada.differential.difference import XorDiff, RXDiff
>>> from cascada.differential.chmodel import CipherChModel
>>> 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)
>>> xor_ch_model  
CipherChModel(ks_ch_model=ChModel(func=SpeckKeySchedule_1R,
    input_diff=[XorDiff(dmk0), XorDiff(dmk1)],
    output_diff=[XorDiff(dmk1_out), XorDiff(dk3_out)],
    assign_outdiff2op_model=[(XorDiff(dk1), XorModelBvAdd([XorDiff(dmk0 >>> 7), XorDiff(dmk1)])),
        (XorDiff(dmk1_out), XorModelId(XorDiff(dmk1))),
        (XorDiff(dk3_out), XorModelId(XorDiff((dmk1 <<< 2) ^ dk1)))]),
enc_ch_model=ChModel(func=SpeckEncryption_2R,
    input_diff=[XorDiff(dp0), XorDiff(dp1)],
    output_diff=[XorDiff(dx7_out), XorDiff(dx9_out)],
    external_var2diff=[(dmk1_out, XorDiff(dmk1_out)), (dk3_out, XorDiff(dk3_out))],
    assign_outdiff2op_model=[(XorDiff(dx1), XorModelBvAdd([XorDiff(dp0 >>> 7), XorDiff(dp1)])),
        (XorDiff(dx6), XorModelBvAdd([XorDiff((dx1 ^ dmk1_out) >>> 7), XorDiff((dp1 <<< 2) ^ dx1 ^ dmk1_out)])),
        (XorDiff(dx7_out), XorModelId(XorDiff(dx6 ^ dk3_out))),
        (XorDiff(dx9_out), XorModelId(XorDiff((((dp1 <<< 2) ^ dx1 ^ dmk1_out) <<< 2) ^ dx6 ^ dk3_out)))]))
>>> xor_ch_model.ks_ch_model.ssa  
SSA(input_vars=[dmk0, dmk1], output_vars=[dmk1_out, dk3_out],
    assignments=[(dk0, dmk0 >>> 7), (dk1, dk0 + dmk1), (dk2, dmk1 <<< 2),
        (dk3, dk2 ^ dk1), (dmk1_out, Id(dmk1)), (dk3_out, Id(dk3))])
>>> xor_ch_model.enc_ch_model.ssa  
SSA(input_vars=[dp0, dp1], output_vars=[dx7_out, dx9_out], external_vars=[dmk1_out, dk3_out],
    assignments=[(dx0, dp0 >>> 7), (dx1, dx0 + dp1), (dx2, dx1 ^ dmk1_out), (dx3, dp1 <<< 2),
        (dx4, dx3 ^ dx2), (dx5, dx2 >>> 7), (dx6, dx5 + dx4), (dx7, dx6 ^ dk3_out), (dx8, dx4 <<< 2),
        (dx9, dx8 ^ dx7), (dx7_out, Id(dx7)), (dx9_out, Id(dx9))])
>>> rx_ch_model = CipherChModel(Speck32, RXDiff)
>>> rx_ch_model  
CipherChModel(ks_ch_model=ChModel(func=SpeckKeySchedule_1R,
    input_diff=[RXDiff(dmk0), RXDiff(dmk1)],
    output_diff=[RXDiff(dmk1_out), RXDiff(dk3_out)],
    assign_outdiff2op_model=[(RXDiff(dk1), RXModelBvAdd([RXDiff(dmk0 >>> 7), RXDiff(dmk1)])),
        (RXDiff(dmk1_out), RXModelId(RXDiff(dmk1))),
        (RXDiff(dk3_out), RXModelId(RXDiff((dmk1 <<< 2) ^ dk1)))]),
    enc_ch_model=ChModel(func=SpeckEncryption_2R,
        input_diff=[RXDiff(dp0), RXDiff(dp1)],
        output_diff=[RXDiff(dx7_out), RXDiff(dx9_out)],
        external_var2diff=[(dmk1_out, RXDiff(dmk1_out)), (dk3_out, RXDiff(dk3_out))],
        assign_outdiff2op_model=[(RXDiff(dx1), RXModelBvAdd([RXDiff(dp0 >>> 7), RXDiff(dp1)])),
            (RXDiff(dx6), RXModelBvAdd([RXDiff((dx1 ^ dmk1_out) >>> 7), RXDiff((dp1 <<< 2) ^ dx1 ^ dmk1_out)])),
            (RXDiff(dx7_out), RXModelId(RXDiff(dx6 ^ dk3_out))),
            (RXDiff(dx9_out), RXModelId(RXDiff((((dp1 <<< 2) ^ dx1 ^ dmk1_out) <<< 2) ^ dx6 ^ dk3_out)))]))
vrepr()[source]

Return an executable string representation.

See also abstractproperty.chmodel.CipherChModel.vrepr.

>>> from cascada.bitvector.core import Variable
>>> from cascada.differential.difference import XorDiff
>>> from cascada.differential.chmodel import CipherChModel
>>> from cascada.primitives import speck
>>> Speck32 = speck.get_Speck_instance(speck.SpeckInstance.speck_32_64)
>>> Speck32.set_num_rounds(2)
>>> CipherChModel(Speck32, XorDiff).vrepr()
'CipherChModel(cipher=SpeckCipher.set_num_rounds_and_return(2), diff_type=XorDiff)'
signature(ch_signature_type)[source]

Return the signature of the characteristic model over the cipher.

See also abstractproperty.chmodel.CipherChModel.signature.

>>> from cascada.bitvector.core import Variable
>>> from cascada.differential.difference import XorDiff
>>> from cascada.differential.chmodel import CipherChModel, ChModelSigType
>>> from cascada.primitives import speck
>>> Speck32 = speck.get_Speck_instance(speck.SpeckInstance.speck_32_64)
>>> Speck32.set_num_rounds(2)
>>> rkch_model = CipherChModel(Speck32, XorDiff)
>>> rkch_model.signature(ChModelSigType.Unique)
[dmk0, dmk1, dk1, dp0, dp1, dmk1_out, dk3_out, dx1, dx6]
>>> rkch_model.signature(ChModelSigType.InputOutput)  
[dmk0, dmk1, dmk1_out, dk3_out, dp0, dp1, dx7_out, dx9_out]