Utils

delete_espresso_dictionary(file_path)
espresso_pos_to_constraints(espresso_inequalities, variables)
generate_espresso_input(valid_points)
generate_product_of_sum_from_espresso(valid_points)

EXAMPLES:

sage: from itertools import product
sage: transitions = [(i1, i2, (i1 + i2) % 2) if (i1 < 2 and i2 < 2) else (i1, i2, 2) for i1, i2 in product(range(3),repeat=2)]
sage: from claasp.cipher_modules.models.milp.utils.utils import generate_product_of_sum_from_espresso
sage: bit_transitions = [ZZ(val[2]).digits(base=2, padto=2) + ZZ(val[1]).digits(base=2, padto=2) + ZZ(val[0]).digits(base=2, padto=2) for val in transitions]
sage: valid_points = ["".join(str(_) for _ in bit_transition[::-1]) for bit_transition in bit_transitions]
sage: espresso_inequalities = generate_product_of_sum_from_espresso(valid_points)
...
milp_and(model, a, b)

Returns constraints to model a and b, where a and b are binary variables. The binary variable a_and_b = 1 iff a == 1 and b == 1

milp_else(var_if, else_constraints, big_m)

Returns a list of variables and a list of constraints to model an else statement.

milp_eq(model, a, b, big_m)

Returns constraints to determine whether a == b, where b is a constant. The binary variable a_eq_b = 1 iff a == b

EXAMPLES:

sage: from claasp.ciphers.block_ciphers.simon_block_cipher import SimonBlockCipher
sage: from claasp.cipher_modules.models.milp.utils.utils import milp_eq
sage: cipher = SimonBlockCipher(block_bit_size=32, key_bit_size=64, number_of_rounds=2)
sage: from claasp.cipher_modules.models.milp.milp_model import MilpModel
sage: M = MilpModel(cipher)
sage: M.init_model_in_sage_milp_class()
sage: mip = M._model
sage: x = M._integer_variable; d = M._binary_variable
sage: a = x[0]; b = 2; big_m = 4
sage: dummy, constraints = milp_eq(M, a, b, big_m)
sage: for i in constraints:
....:     mip.add_constraint(i)
sage: dummy
x_3
sage: constraints
[x_0 <= 6 - 4*x_1,
 3 - 4*x_1 <= x_0,
 2 <= 4 + x_0 - 4*x_2,
 1 + x_0 - 4*x_2 <= 2,
 -1 + x_1 + x_2 <= x_3,
 x_3 <= x_1,
 x_3 <= x_2]
milp_generalized_and(model, var_list)

Returns constraints to model a_0 and a_1 and … a_n-1, where a_i’s are binary variables in var_list. The binary variable generalized_and = 1 iff a_i == 1 for all i.

EXAMPLES:

sage: from claasp.ciphers.block_ciphers.simon_block_cipher import SimonBlockCipher
sage: from claasp.cipher_modules.models.milp.utils.utils import milp_generalized_and
sage: cipher = SimonBlockCipher(block_bit_size=32, key_bit_size=64, number_of_rounds=2)
sage: from claasp.cipher_modules.models.milp.milp_model import MilpModel
sage: M = MilpModel(cipher)
sage: M.init_model_in_sage_milp_class()
sage: mip = M._model
sage: d = M._binary_variable
sage: var_list = [d[i] for i in range(4)]
sage: general_and, constraints = milp_generalized_and(M, var_list)
sage: for i in constraints:
....:     mip.add_constraint(i)
sage: general_and
x_4
sage: constraints
[-3 + x_0 + x_1 + x_2 + x_3 <= x_4,
 x_4 <= x_0,
 x_4 <= x_1,
 x_4 <= x_2,
 x_4 <= x_3]
milp_generalized_xor(input_var_list, output_bit)

Returns constraints to model a_0 xor a_1 xor … xor a_{n-1} = output_bit for binary variables

EXAMPLES:

sage: from claasp.cipher_modules.models.milp.utils.utils import milp_generalized_xor
sage: from claasp.ciphers.block_ciphers.simon_block_cipher import SimonBlockCipher
sage: cipher = SimonBlockCipher(block_bit_size=32, key_bit_size=64, number_of_rounds=2)
sage: from claasp.cipher_modules.models.milp.milp_model import MilpModel
sage: M = MilpModel(cipher)
sage: M.init_model_in_sage_milp_class()
sage: mip = M._model
sage: x = M._binary_variable
sage: var_list = [x[i] for i in range(2)]; b = x[2]
sage: for i in milp_generalized_xor(var_list, b):
....:     mip.add_constraint(i)
...
sage: var_list
[x_0, x_1]
milp_geq(model, a, b, big_m)

Returns constraints to determine whether a >= b, where a and b are integer variables or constants. The binary variable a_geq_b = 1 iff a >= b

milp_greater(model, a, b, big_m)

Returns constraints to determine whether a > b, where a and b are integer variables or constants. The binary variable a_greater_b = 1 iff a > b

milp_if_elif_else(model, var_if_list, then_constraints_list, else_constraints, big_m)

Returns a list of variables and a list of constraints to model an if-elif…-elif-else statement. When the binary variable var_if[i] == 1, the set ‘then_constraints[i]’ is applied, when all var_if variables are 0, the set ‘else_constraints’ is applied

https://stackoverflow.com/questions/41009196/if-then-elseif-then-in-mixed-integer-linear-programming

milp_if_then(var_if, then_constraints, big_m)

Returns a list of variables and a list of constraints to model an if-then statement. When the binary variable var_if == 1, the set ‘then_constraints’ is applied.

milp_if_then_else(var_if, then_constraints, else_constraints, big_m)

Returns a list of variables and a list of constraints to model an if-then-else statement. When the binary variable var_if == 1, the set ‘then_constraints’ is applied, when var_if == 0, the set ‘else_constraints’ is applied

milp_leq(model, a, b, big_m)

Returns constraints to determine whether a <= b, where a and b are integer variables or constants. The binary variable a_leq_b = 1 iff a <= b

milp_less(model, a, b, big_m)

Returns constraints to determine whether a < b, where ‘a’ is an integer variables and ‘b’ is an integer variable or a constant. The binary variable a_less_b = 1 iff a < b

EXAMPLES:

sage: from claasp.ciphers.block_ciphers.simon_block_cipher import SimonBlockCipher
sage: from claasp.cipher_modules.models.milp.utils.utils import milp_less
sage: cipher = SimonBlockCipher(block_bit_size=32, key_bit_size=64, number_of_rounds=2)
sage: from claasp.cipher_modules.models.milp.milp_model import MilpModel
sage: M = MilpModel(cipher)
sage: M.init_model_in_sage_milp_class()
sage: mip = M._model
sage: x = M._integer_variable; d = M._binary_variable
sage: mip.set_max(x,2); mip.set_min(x,0)
sage: a = x[0]; b = x[1]; big_m = 4
sage: dummy, constraints = milp_less(M, a, b, big_m)
sage: for i in constraints:
....:     mip.add_constraint(i)
sage: dummy
x_2
sage: constraints
[x_0 <= 3 + x_1 - 4*x_2, x_1 - 4*x_2 <= x_0]
milp_neq(model, a, b, big_m)

Returns constraints to determine whether a != b, where b is a constant. The binary variable a_neq_b = 1 iff a != b

EXAMPLES:

sage: from claasp.ciphers.block_ciphers.simon_block_cipher import SimonBlockCipher
sage: from claasp.cipher_modules.models.milp.utils.utils import milp_neq
sage: cipher = SimonBlockCipher(block_bit_size=32, key_bit_size=64, number_of_rounds=2)
sage: from claasp.cipher_modules.models.milp.milp_model import MilpModel
sage: M = MilpModel(cipher)
sage: M.init_model_in_sage_milp_class()
sage: mip = M._model
sage: x = M._integer_variable; d = M._binary_variable
sage: a = x[0]; b = 2; big_m = 4
sage: dummy, constraints = milp_neq(M, a, b, big_m)
sage: for i in constraints:
....:     mip.add_constraint(i)
sage: dummy
x_3
sage: constraints
[x_0 <= 5 - 4*x_1,
 2 - 4*x_1 <= x_0,
 2 <= 3 + x_0 - 4*x_2,
 x_0 - 4*x_2 <= 2,
 x_3 <= x_1 + x_2,
 x_1 <= x_3,
 x_2 <= x_3]
milp_or(model, a, b)

Returns constraints to model a or b, where a and b are binary variables. The binary variable a_or_b = 1 iff a == 1 or b == 1

milp_xor(a, b, c)

Returns constraints to model a xor b = c for binary variables

EXAMPLES:

sage: from claasp.ciphers.block_ciphers.simon_block_cipher import SimonBlockCipher
sage: from claasp.cipher_modules.models.milp.utils.utils import milp_xor
sage: cipher = SimonBlockCipher(block_bit_size=32, key_bit_size=64, number_of_rounds=2)
sage: from claasp.cipher_modules.models.milp.milp_model import MilpModel
sage: M = MilpModel(cipher)
sage: M.init_model_in_sage_milp_class()
sage: mip = M._model
sage: x = M._binary_variable
sage: a = x[0]; b = x[1]; c = x[2]
sage: for i in milp_xor(a,b,c):
....:     mip.add_constraint(i)
sage: a
x_0
milp_xor_truncated(model, input_1, input_2, output)

Returns a list of variables and a list of constraints for the XOR for two input bits in the deterministic truncated XOR differential model.

This method uses a binary encoding (where each variable v is seen as a binary tuple (v0, v1), where v0 is the MSB) to model the result c of the truncated XOR between inputs a and b.

a | b | c

0 | 0 | 0 0 | 1 | 1 0 | 2 | 2 1 | 0 | 1 1 | 1 | 0 1 | 2 | 2 2 | 0 | 2 2 | 1 | 2 2 | 2 | 2

The table can be obtained with the following lines:

sage: from itertools import product sage: transitions = [(i1, i2, (i1 + i2) % 2) if (i1 < 2 and i2 < 2) else (i1, i2, 2) for i1, i2 in product(range(3),repeat=2)]

Espresso was used to reduce the number of constraints to 10 inequalities:

sage: from claasp.cipher_modules.models.milp.utils.utils import generate_product_of_sum_from_espresso sage: bit_transitions = [ZZ(val[2]).digits(base=2, padto=2) + ZZ(val[1]).digits(base=2, padto=2) + ZZ(val[0]).digits(base=2, padto=2) for val in transitions] sage: valid_points = [“”.join(str(_) for _ in bit_transition[::-1]) for bit_transition in bit_transitions] sage: espresso_inequalities = generate_product_of_sum_from_espresso(valid_points)

milp_xor_truncated_wordwise(model, input_1, input_2, output)

Returns a list of variables and a list of constraints for the XOR for two input bytes in deterministic truncated XOR differential model.

This method uses a binary encoding (where each variable v is seen as a binary tuple (v0, v1), where v0 is the MSB) to model the result c of the truncated XOR between inputs a and b.

a | b | c

0 | 0 | 0 0 | 1 | 1 0 | 2 | 2 0 | 3 | 3 1 | 0 | 1 1 | 1 | 0 1 | 1 | 1 1 | 2 | 3 1 | 3 | 3 2 | 0 | 2 2 | 1 | 3 2 | 2 | 3 2 | 3 | 3 3 | 0 | 3 3 | 1 | 3 3 | 2 | 3 3 | 3 | 3

Espresso was used to reduce the number of constraints to 91 inequalities.

output_espresso_dictionary(file_path)