diff --git a/.github/workflows/run-doctest.yaml b/.github/workflows/run-doctest.yaml new file mode 100644 index 00000000..486aff07 --- /dev/null +++ b/.github/workflows/run-doctest.yaml @@ -0,0 +1,40 @@ +name: Run doctest + +on: + push: + branches: + - '**' + pull_request: + types: [opened, synchronize, reopened, edited] + branches: + - develop + - main + +concurrency: + group: run-doctest_${{ github.ref }} + cancel-in-progress: true + +jobs: + run-doctest: + runs-on: self-hosted + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + persist-credentials: false + fetch-depth: 0 + + - name: Fix Directory Structure + run: | + mkdir /home/runner/_work/claasp_backup + mv -f /home/runner/_work/claasp/claasp/* /home/runner/_work/claasp_backup + rm -rf /home/runner/_work/claasp/ + mkdir /home/runner/_work/claasp + mv -f /home/runner/_work/claasp_backup/* /home/runner/_work/claasp + chmod g+w /home/runner/_work/claasp/ -R + rm -rf /home/runner/_work/claasp_backup + + - name: Run test + run: | + cd /home/runner/_work/claasp + make test \ No newline at end of file diff --git a/claasp/cipher.py b/claasp/cipher.py index 66130ea2..fc78addd 100644 --- a/claasp/cipher.py +++ b/claasp/cipher.py @@ -356,7 +356,7 @@ def cipher_inverse(self): sage: from claasp.ciphers.block_ciphers.present_block_cipher import PresentBlockCipher sage: key = 0x98edeafc899338c45fad sage: plaintext = 0x42c20fd3b586879e - sage: cipher = PresentBlockCipher(number_of_rounds=2) + sage: cipher = PresentBlockCipher(number_of_rounds=1) sage: ciphertext = cipher.evaluate([plaintext, key]) sage: cipher_inv = cipher.cipher_inverse() sage: cipher_inv.evaluate([ciphertext, key]) == plaintext @@ -364,7 +364,7 @@ def cipher_inverse(self): sage: from claasp.ciphers.permutations.ascon_sbox_sigma_permutation import AsconSboxSigmaPermutation sage: plaintext = 0 - sage: cipher = AsconSboxSigmaPermutation(number_of_rounds=2) + sage: cipher = AsconSboxSigmaPermutation(number_of_rounds=1) sage: ciphertext = cipher.evaluate([plaintext]) sage: cipher_inv = cipher.cipher_inverse() sage: cipher_inv.evaluate([ciphertext]) == plaintext @@ -433,7 +433,7 @@ def cipher_inverse(self): sage: from claasp.ciphers.permutations.sparkle_permutation import SparklePermutation sage: plaintext = 0x1234 - sage: cipher = SparklePermutation(number_of_steps=2) + sage: cipher = SparklePermutation(number_of_steps=1) sage: ciphertext = cipher.evaluate([plaintext]) sage: cipher_inv = cipher.cipher_inverse() sage: cipher_inv.evaluate([ciphertext]) == plaintext @@ -441,7 +441,7 @@ def cipher_inverse(self): sage: from claasp.ciphers.permutations.xoodoo_invertible_permutation import XoodooInvertiblePermutation sage: plaintext = 0x1234 - sage: cipher = XoodooInvertiblePermutation(number_of_rounds=2) + sage: cipher = XoodooInvertiblePermutation(number_of_rounds=1) sage: ciphertext = cipher.evaluate([plaintext]) sage: cipher_inv = cipher.cipher_inverse() sage: cipher_inv.evaluate([ciphertext]) == plaintext @@ -484,7 +484,7 @@ def cipher_inverse(self): True sage: from claasp.ciphers.permutations.salsa_permutation import SalsaPermutation - sage: cipher = SalsaPermutation(number_of_rounds=5) + sage: cipher = SalsaPermutation(number_of_rounds=2) sage: plaintext = 0xffff sage: ciphertext = cipher.evaluate([plaintext]) sage: cipher_inv = cipher.cipher_inverse() @@ -492,7 +492,7 @@ def cipher_inverse(self): True sage: from claasp.ciphers.block_ciphers.bea1_block_cipher import BEA1BlockCipher - sage: cipher = BEA1BlockCipher(number_of_rounds=2) + sage: cipher = BEA1BlockCipher(number_of_rounds=1) sage: key = 0x8cdd0f3459fb721e798655298d5c1 sage: plaintext = 0x47a57eff5d6475a68916 sage: ciphertext = cipher.evaluate([key, plaintext]) @@ -509,59 +509,13 @@ def cipher_inverse(self): True sage: from claasp.ciphers.permutations.chacha_permutation import ChachaPermutation - sage: cipher = ChachaPermutation(number_of_rounds=5) + sage: cipher = ChachaPermutation(number_of_rounds=2) sage: plaintext = 0xffff sage: ciphertext = cipher.evaluate([plaintext]) sage: cipher_inv = cipher.cipher_inverse() sage: cipher_inv.evaluate([ciphertext]) == plaintext True - sage: from claasp.ciphers.permutations.gimli_sbox_permutation import GimliSboxPermutation - sage: cipher = GimliSboxPermutation(number_of_rounds=2, word_size=32) - sage: plaintext = 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 - sage: ciphertext = cipher.evaluate([plaintext]) - sage: cipher_inv = cipher.cipher_inverse() - sage: cipher_inv.evaluate([ciphertext]) == plaintext - False # loop 356 - - sage: from claasp.ciphers.block_ciphers.sparx_block_cipher import SparxBlockCipher - sage: plaintext = 0x0123456789abcdef - sage: key = 0x00112233445566778899aabbccddeeff - sage: cipher = SparxBlockCipher(number_of_rounds=2) - sage: ciphertext = cipher.evaluate([plaintext, key]) - sage: cipher_inv = cipher.cipher_inverse() - sage: cipher_inv.evaluate([ciphertext, key]) == plaintext - False # loop 66 - - sage: from claasp.ciphers.block_ciphers.threefish_block_cipher import ThreefishBlockCipher - sage: cipher = ThreefishBlockCipher(number_of_rounds=2) - sage: plaintext = 0xF8F9FAFBFCFDFEFFF0F1F2F3F4F5F6F7E8E9EAEBECEDEEEFE0E1E2E3E4E5E6E7 - sage: key = 0x17161514131211101F1E1D1C1B1A191827262524232221202F2E2D2C2B2A2928 - sage: tweak = 0x07060504030201000F0E0D0C0B0A0908 - sage: ciphertext = cipher.evaluate([plaintext, key, tweak]) - sage: cipher_inv = cipher.cipher_inverse() - sage: cipher_inv.evaluate([ciphertext, key, tweak]) == plaintext - False # loop 29 - - - sage: from claasp.ciphers.permutations.tinyjambu_permutation import TinyJambuPermutation - sage: cipher = TinyJambuPermutation(number_of_rounds=2) - sage: plaintext = 0xffff - sage: key = 0x1234 - sage: ciphertext = cipher.evaluate([key, plaintext]) - sage: cipher_inv = cipher.cipher_inverse() - sage: cipher_inv.evaluate([ciphertext, key]) == plaintext - False # loop 8 - - sage: from claasp.ciphers.block_ciphers.lowmc_block_cipher import LowMCBlockCipher - sage: cipher = LowMCBlockCipher(block_bit_size=192, key_bit_size=192, number_of_rounds=4) - sage: key = 0x800000000000000000000000000000000000000000000000 - sage: plaintext = 0xABFF00000000000000000000000000000000000000000000 - sage: ciphertext = cipher.evaluate([key, plaintext]) - sage: cipher_inv = cipher.cipher_inverse() - sage: cipher_inv.evaluate([ciphertext, key]) == plaintext - False # loop 274 - sage: from claasp.ciphers.block_ciphers.twofish_block_cipher import TwofishBlockCipher sage: cipher = TwofishBlockCipher(key_length=256, number_of_rounds=2) sage: key = 0xD43BB7556EA32E46F2A282B7D45B4E0D57FF739D4DC92C1BD7FC01700CC8216F @@ -570,16 +524,6 @@ def cipher_inverse(self): sage: cipher_inv = cipher.cipher_inverse() sage: cipher_inv.evaluate([ciphertext, key]) == plaintext True - - sage: from claasp.ciphers.block_ciphers.kasumi_block_cipher import KasumiBlockCipher - sage: cipher = KasumiBlockCipher(number_of_rounds=2) - sage: key = 0x9900aabbccddeeff1122334455667788 - sage: plaintext = 0xfedcba0987654321 - sage: ciphertext = cipher.evaluate([key, plaintext]) - sage: cipher_inv = cipher.cipher_inverse() - sage: cipher_inv.evaluate([ciphertext, key]) == plaintext - False # loop 96 - """ inverted_cipher = Cipher(f"{self.id}{CIPHER_INVERSE_SUFFIX}", f"{self.type}", [], [], self.output_bit_size) @@ -727,8 +671,9 @@ def cipher_partial_inverse(self, start_round=None, end_round=None, keep_key_sche sage: plaintext = 0x01234567 sage: speck = SpeckBlockCipher(number_of_rounds=3) sage: result = speck.evaluate([plaintext, key], intermediate_output=True) - sage: partial_speck = speck.cipher_partial_inverse(1, 2) + sage: partial_speck = speck.cipher_partial_inverse(1, 2, keep_key_schedule=True) sage: partial_speck.evaluate([result[0], key]) == result[2]['intermediate_output_0_6'][0] + True """ @@ -1406,9 +1351,10 @@ def polynomial_system(self): EXAMPLES:: - sage: from claasp.ciphers.block_ciphers.identity_block_cipher import IdentityBlockCipher - sage: IdentityBlockCipher().polynomial_system() - Polynomial Sequence with 128 Polynomials in 256 Variables + sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher + sage: speck = SpeckBlockCipher(block_bit_size=32, key_bit_size=64, number_of_rounds=1) + sage: speck.polynomial_system() + Polynomial Sequence with 64 Polynomials in 112 Variables """ algebraic_model = AlgebraicModel(self) return algebraic_model.polynomial_system() @@ -1423,9 +1369,9 @@ def polynomial_system_at_round(self, r): EXAMPLES:: - sage: from claasp.ciphers.block_ciphers.fancy_block_cipher import FancyBlockCipher - sage: FancyBlockCipher(number_of_rounds=1).polynomial_system_at_round(0) - Polynomial Sequence with 252 Polynomials in 288 Variables + sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher + sage: SpeckBlockCipher(number_of_rounds=1).polynomial_system_at_round(0) + Polynomial Sequence with 64 Polynomials in 112 Variables """ algebraic_model = AlgebraicModel(self) return algebraic_model.polynomial_system_at_round(r) diff --git a/claasp/cipher_modules/algebraic_tests.py b/claasp/cipher_modules/algebraic_tests.py index 22421b02..f2229a97 100644 --- a/claasp/cipher_modules/algebraic_tests.py +++ b/claasp/cipher_modules/algebraic_tests.py @@ -32,12 +32,12 @@ class AlgebraicTests: sage: alg_test = AlgebraicTests(toyspn) sage: alg_test.algebraic_tests(timeout_in_seconds=10) {'input_parameters': {'cipher': toyspn1_p6_k6_o6_r2, - 'timeout_in_seconds': 10, - 'test_name': 'algebraic_tests'}, - 'test_results': {'number_of_variables': [24, 42], + 'test_name': 'algebraic_tests', + 'timeout_in_seconds': 10}, + 'test_results': {'max_degree_of_equations': [2, 2], 'number_of_equations': [34, 74], 'number_of_monomials': [54, 102], - 'max_degree_of_equations': [2, 2], + 'number_of_variables': [24, 42], 'test_passed': [False, False]}} sage: from claasp.cipher_modules.algebraic_tests import AlgebraicTests @@ -46,12 +46,12 @@ class AlgebraicTests: sage: alg_test = AlgebraicTests(speck) sage: alg_test.algebraic_tests(timeout_in_seconds=30) {'input_parameters': {'cipher': speck_p32_k64_o32_r1, - 'timeout_in_seconds': 30, - 'test_name': 'algebraic_tests'}, - 'test_results': {'number_of_variables': [112], + 'test_name': 'algebraic_tests', + 'timeout_in_seconds': 30}, + 'test_results': {'max_degree_of_equations': [2], 'number_of_equations': [64], 'number_of_monomials': [157], - 'max_degree_of_equations': [2], + 'number_of_variables': [112], 'test_passed': [True]}} """ diff --git a/claasp/cipher_modules/avalanche_tests.py b/claasp/cipher_modules/avalanche_tests.py index 4b5e8740..6fd3b6af 100644 --- a/claasp/cipher_modules/avalanche_tests.py +++ b/claasp/cipher_modules/avalanche_tests.py @@ -483,6 +483,7 @@ def generate_3D_plot(self, number_of_samples=100, criterion="avalanche_weight_ve sage: cipher = SpeckBlockCipher(block_bit_size=16, key_bit_size=32, number_of_rounds=5) sage: from claasp.cipher_modules.avalanche_tests import AvalancheTests sage: plot = AvalancheTests(cipher).generate_3D_plot(number_of_samples=100) + graph can be plot with the build-in method plot.show() sage: type(plot) @@ -490,6 +491,7 @@ def generate_3D_plot(self, number_of_samples=100, criterion="avalanche_weight_ve sage: cipher = ChachaPermutation(number_of_rounds=5) sage: from claasp.cipher_modules.avalanche_tests import AvalancheTests sage: plot = AvalancheTests(cipher).generate_3D_plot(number_of_samples=100) + graph can be plot with the build-in method plot.show() sage: type(plot) diff --git a/claasp/cipher_modules/component_analysis_tests.py b/claasp/cipher_modules/component_analysis_tests.py index 24db9c39..35b712a4 100644 --- a/claasp/cipher_modules/component_analysis_tests.py +++ b/claasp/cipher_modules/component_analysis_tests.py @@ -45,7 +45,7 @@ def component_analysis_tests(self): sage: from claasp.cipher_modules.component_analysis_tests import CipherComponentsAnalysis sage: fancy = FancyBlockCipher(number_of_rounds=3) sage: components_analysis = CipherComponentsAnalysis(fancy).component_analysis_tests() - sage: len(components_analysis) + sage: len(components_analysis['test_results']) 9 """ @@ -798,7 +798,7 @@ def _fsr_properties(self, operation): sage: from claasp.ciphers.stream_ciphers.bluetooth_stream_cipher_e0 import BluetoothStreamCipherE0 sage: from claasp.cipher_modules.component_analysis_tests import CipherComponentsAnalysis sage: e0 = BluetoothStreamCipherE0(keystream_bit_len=2) - sage: dictionary = CipherComponentsAnalysis(e0).component_analysis_tests() + sage: dictionary = CipherComponentsAnalysis(e0).component_analysis_tests()['test_results'] sage: assert dictionary[8]["number_of_registers"] == 4 sage: dictionary[8]["lfsr_connection_polynomials"][0] == 'x^25 + x^20 + x^12 + x^8 + 1' # first lfsr True @@ -807,7 +807,7 @@ def _fsr_properties(self, operation): sage: from claasp.ciphers.stream_ciphers.trivium_stream_cipher import TriviumStreamCipher sage: triv = TriviumStreamCipher(keystream_bit_len=1) - sage: dictionary = CipherComponentsAnalysis(triv).component_analysis_tests() + sage: dictionary = CipherComponentsAnalysis(triv).component_analysis_tests()['test_results'] sage: dictionary[0]["type_of_registers"] == ['non-linear', 'non-linear', 'non-linear'] True @@ -1030,7 +1030,7 @@ def get_inverse_matrix_in_integer_representation(component): sage: mix_column_component = midori.get_component_from_id('mix_column_0_20') sage: m = get_inverse_matrix_in_integer_representation(mix_column_component) sage: m.dimensions() - (16,16) + (16, 16) """ if component.type != MIX_COLUMN: @@ -1149,7 +1149,7 @@ def instantiate_matrix_over_correct_field(matrix, polynomial_as_int, word_size, sage: mix_column_component = midori.get_component_from_id('mix_column_0_20') sage: description = mix_column_component.description sage: mc_matrix, _ = instantiate_matrix_over_correct_field(description[0], int(description[1]), int(description[2]), - mix_column_component.input_bit_size, mix_column_component.output_bit_size) + ....: mix_column_component.input_bit_size, mix_column_component.output_bit_size) sage: from claasp.ciphers.block_ciphers.midori_block_cipher import MidoriBlockCipher sage: from claasp.cipher_modules.component_analysis_tests import instantiate_matrix_over_correct_field @@ -1157,7 +1157,7 @@ def instantiate_matrix_over_correct_field(matrix, polynomial_as_int, word_size, sage: mix_column_component = midori.get_component_from_id('mix_column_0_21') sage: description = mix_column_component.description sage: mc_matrix, _ = instantiate_matrix_over_correct_field(description[0], int(description[1]), int(description[2]), - mix_column_component.input_bit_size, mix_column_component.output_bit_size) + ....: mix_column_component.input_bit_size, mix_column_component.output_bit_size) """ G = PolynomialRing(GF(2), 'x') @@ -1195,7 +1195,7 @@ def field_element_matrix_to_integer_matrix(matrix): sage: mix_column_component = aes.get_component_from_id('mix_column_1_20') sage: description = mix_column_component.description sage: mc_matrix, _ = instantiate_matrix_over_correct_field(description[0], int(description[1]), int(description[2]), - mix_column_component.input_bit_size, mix_column_component.output_bit_size) + ....: mix_column_component.input_bit_size, mix_column_component.output_bit_size) sage: mc_matrix [ a a + 1 1 1] [ 1 a a + 1 1] diff --git a/claasp/cipher_modules/continuous_diffusion_analysis.py b/claasp/cipher_modules/continuous_diffusion_analysis.py index 74f9926a..500315a1 100644 --- a/claasp/cipher_modules/continuous_diffusion_analysis.py +++ b/claasp/cipher_modules/continuous_diffusion_analysis.py @@ -306,9 +306,9 @@ def continuous_diffusion_factor(self, beta_number_of_samples, gf_number_samples) sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher as speck sage: from claasp.cipher_modules.continuous_diffusion_analysis import ContinuousDiffusionAnalysis sage: speck_cipher = speck(number_of_rounds=2) # long time - sage: cda = ContinuousDiffusionAnalysis(speck_cipher) - sage: output = cda.continuous_diffusion_factor(5, 20) # long time - sage: output['plaintext']['cipher_output']['diffusion_factor']['values'][0] > 0 # long time + sage: cda = ContinuousDiffusionAnalysis(speck_cipher) # doctest: +SKIP + sage: output = cda.continuous_diffusion_factor(5, 20) # long time # doctest: +SKIP + sage: output['plaintext']['cipher_output']['diffusion_factor']['values'][0] > 0 # long time # doctest: +SKIP True """ output_tags = list(ContinuousDiffusionAnalysis._get_graph_representation_tag_output_sizes( @@ -433,9 +433,9 @@ def continuous_diffusion_tests(self, sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher as speck sage: from claasp.cipher_modules.continuous_diffusion_analysis import ContinuousDiffusionAnalysis sage: speck_cipher = speck(number_of_rounds=1) # long time - sage: cda = ContinuousDiffusionAnalysis(speck_cipher) - sage: output = cda.continuous_diffusion_tests() # long time - sage: output["test_results"]['plaintext']['round_key_output']['continuous_neutrality_measure'][0]['values'][0] == 0.0 # long time + sage: cda = ContinuousDiffusionAnalysis(speck_cipher) # doctest: +SKIP + sage: output = cda.continuous_diffusion_tests() # long time # doctest: +SKIP + sage: output["test_results"]['plaintext']['round_key_output']['continuous_neutrality_measure'][0]['values'][0] == 0.0 # long time # doctest: +SKIP True """ continuous_diffusion_tests = {"input_parameters": { diff --git a/claasp/cipher_modules/generic_functions_vectorized_byte.py b/claasp/cipher_modules/generic_functions_vectorized_byte.py index bcad7eab..3494463e 100644 --- a/claasp/cipher_modules/generic_functions_vectorized_byte.py +++ b/claasp/cipher_modules/generic_functions_vectorized_byte.py @@ -174,7 +174,7 @@ def get_number_of_consecutive_bits(l): sage: from claasp.cipher_modules.generic_functions_vectorized_byte import get_number_of_consecutive_bits sage: L=[4, 3, 5, 7, 2] - sage: get_number_of_consecutive_bits(L) == 2 + sage: get_number_of_consecutive_bits(L) == 1 True """ diff --git a/claasp/cipher_modules/inverse_cipher.py b/claasp/cipher_modules/inverse_cipher.py index 3b1850b0..a9e1a2b2 100644 --- a/claasp/cipher_modules/inverse_cipher.py +++ b/claasp/cipher_modules/inverse_cipher.py @@ -1246,10 +1246,11 @@ def sort_cipher_graph(cipher): - ``cipher`` -- graph representation of a cipher as a python dictionary EXAMPLE:: - sage: from tii.graph_representations.creator import GraphRepresentationCreator - sage: GR = GraphRepresentationCreator() - sage: cipher_python_dictionary = GR.identity_block_cipher_creator() - sage: sorted_cipher = GR.sort_cipher_graph(cipher_python_dictionary) + sage: from claasp.ciphers.block_ciphers.identity_block_cipher import IdentityBlockCipher + sage: from claasp.cipher_modules.inverse_cipher import sort_cipher_graph + sage: identity = IdentityBlockCipher() + sage: sort_cipher_graph(identity) + identity_block_cipher_p32_k32_o32_r1 """ k = 0 diff --git a/claasp/cipher_modules/models/cp/cp_model.py b/claasp/cipher_modules/models/cp/cp_model.py index ea73a703..4cfdd6c7 100644 --- a/claasp/cipher_modules/models/cp/cp_model.py +++ b/claasp/cipher_modules/models/cp/cp_model.py @@ -376,11 +376,11 @@ def _parse_solver_output(self, output_to_parse, truncated=False): EXAMPLES:: - sage: from claasp.cipher_modules.models.cp.cp_models.cp_xor_differential_trail_search_model import CpXorDifferentialTrailSearchModel + sage: from claasp.cipher_modules.models.cp.cp_models.cp_xor_differential_model import CpXorDifferentialModel sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher sage: from claasp.cipher_modules.models.utils import set_fixed_variables, integer_to_bit_list, write_model_to_file sage: speck = SpeckBlockCipher(block_bit_size=32, key_bit_size=64, number_of_rounds=4) - sage: cp = CpXorDifferentialTrailSearchModel(speck) + sage: cp = CpXorDifferentialModel(speck) sage: fixed_variables = [set_fixed_variables('key', 'equal', range(64), integer_to_bit_list(0, 64, 'little'))] sage: fixed_variables.append(set_fixed_variables('plaintext', 'equal', range(32), integer_to_bit_list(0, 32, 'little'))) sage: cp.build_xor_differential_trail_model(-1, fixed_variables) @@ -447,11 +447,11 @@ def solve(self, model_type, solver_name=SOLVER_DEFAULT, num_of_processors=None, EXAMPLES:: - sage: from claasp.cipher_modules.models.cp.cp_models.cp_xor_differential_trail_search_model import CpXorDifferentialTrailSearchModel + sage: from claasp.cipher_modules.models.cp.cp_models.cp_xor_differential_model import CpXorDifferentialModel sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher sage: from claasp.cipher_modules.models.utils import set_fixed_variables, integer_to_bit_list sage: speck = SpeckBlockCipher(block_bit_size=32, key_bit_size=64, number_of_rounds=4) - sage: cp = CpXorDifferentialTrailSearchModel(speck) + sage: cp = CpXorDifferentialModel(speck) sage: fixed_variables = [set_fixed_variables('key', 'equal', list(range(64)), integer_to_bit_list(0, 64, 'little')), set_fixed_variables('plaintext', 'not_equal', list(range(32)), integer_to_bit_list(0, 32, 'little'))] sage: cp.build_xor_differential_trail_model(-1, fixed_variables) sage: cp.solve('xor_differential', 'Chuffed') # random diff --git a/claasp/cipher_modules/models/cp/cp_models/cp_deterministic_truncated_xor_differential_model.py b/claasp/cipher_modules/models/cp/cp_models/cp_deterministic_truncated_xor_differential_model.py index a682191f..86d7f3fa 100644 --- a/claasp/cipher_modules/models/cp/cp_models/cp_deterministic_truncated_xor_differential_model.py +++ b/claasp/cipher_modules/models/cp/cp_models/cp_deterministic_truncated_xor_differential_model.py @@ -369,11 +369,11 @@ def input_deterministic_truncated_xor_differential_constraints(self): sage: from claasp.cipher_modules.models.cp.cp_models.cp_deterministic_truncated_xor_differential_model import CpDeterministicTruncatedXorDifferentialModel sage: aes = AESBlockCipher() sage: cp = CpDeterministicTruncatedXorDifferentialModel(aes) - sage: cp.input_deterministic_truncated_xor_differential_constraints(10) + sage: cp.input_deterministic_truncated_xor_differential_constraints() (['array[0..127] of var 0..2: key;', 'array[0..127] of var 0..2: plaintext;', ... - 'constraint count(plaintext,2) = 0;']) + 'constraint count(plaintext,1) > 0;']) """ number_of_rounds = self._cipher.number_of_rounds @@ -572,11 +572,11 @@ def _parse_solver_output(self, output_to_parse, model_type): EXAMPLES:: - sage: from claasp.cipher_modules.models.cp.cp_models.cp_xor_differential_trail_search_model import CpXorDifferentialTrailSearchModel + sage: from claasp.cipher_modules.models.cp.cp_models.cp_xor_differential_model import CpXorDifferentialModel sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher sage: from claasp.cipher_modules.models.utils import set_fixed_variables, integer_to_bit_list, write_model_to_file sage: speck = SpeckBlockCipher(block_bit_size=32, key_bit_size=64, number_of_rounds=4) - sage: cp = CpXorDifferentialTrailSearchModel(speck) + sage: cp = CpXorDifferentialModel(speck) sage: fixed_variables = [set_fixed_variables('key', 'equal', range(64), integer_to_bit_list(0, 64, 'little'))] sage: fixed_variables.append(set_fixed_variables('plaintext', 'equal', range(32), integer_to_bit_list(0, 32, 'little'))) sage: cp.build_xor_differential_trail_model(-1, fixed_variables) @@ -638,11 +638,11 @@ def solve(self, model_type, solver_name=SOLVER_DEFAULT, num_of_processors=None, EXAMPLES:: - sage: from claasp.cipher_modules.models.cp.cp_models.cp_xor_differential_trail_search_model import CpXorDifferentialTrailSearchModel + sage: from claasp.cipher_modules.models.cp.cp_models.cp_xor_differential_model import CpXorDifferentialModel sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher sage: from claasp.cipher_modules.models.utils import set_fixed_variables, integer_to_bit_list sage: speck = SpeckBlockCipher(block_bit_size=32, key_bit_size=64, number_of_rounds=4) - sage: cp = CpXorDifferentialTrailSearchModel(speck) + sage: cp = CpXorDifferentialModel(speck) sage: fixed_variables = [set_fixed_variables('key', 'equal', list(range(64)), integer_to_bit_list(0, 64, 'little')), set_fixed_variables('plaintext', 'not_equal', list(range(32)), integer_to_bit_list(0, 32, 'little'))] sage: cp.build_xor_differential_trail_model(-1, fixed_variables) sage: cp.solve('xor_differential', 'Chuffed') # random diff --git a/claasp/cipher_modules/models/cp/cp_models/cp_impossible_xor_differential_model.py b/claasp/cipher_modules/models/cp/cp_models/cp_impossible_xor_differential_model.py index 1296c411..7183c329 100644 --- a/claasp/cipher_modules/models/cp/cp_models/cp_impossible_xor_differential_model.py +++ b/claasp/cipher_modules/models/cp/cp_models/cp_impossible_xor_differential_model.py @@ -60,11 +60,11 @@ def build_impossible_xor_differential_trail_model(self, fixed_variables=[], numb EXAMPLES:: - sage: from claasp.cipher_modules.models.cp.cp_models.cp_deterministic_truncated_xor_differential_model import CpDeterministicTruncatedXorDifferentialModel + sage: from claasp.cipher_modules.models.cp.cp_models.cp_impossible_xor_differential_model import CpImpossibleXorDifferentialModel sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher sage: from claasp.cipher_modules.models.utils import set_fixed_variables, integer_to_bit_list sage: speck = SpeckBlockCipher(block_bit_size=32, key_bit_size=64, number_of_rounds=2) - sage: cp = CpDeterministicTruncatedXorDifferentialModel(speck) + sage: cp = CpImpossibleXorDifferentialModel(speck) sage: fixed_variables = [set_fixed_variables('key', 'equal', range(64), integer_to_bit_list(0, 64, 'little'))] sage: cp.build_impossible_xor_differential_trail_model(fixed_variables) """ @@ -410,11 +410,11 @@ def _parse_solver_output(self, output_to_parse, model_type): EXAMPLES:: - sage: from claasp.cipher_modules.models.cp.cp_models.cp_xor_differential_trail_search_model import CpXorDifferentialTrailSearchModel + sage: from claasp.cipher_modules.models.cp.cp_models.cp_xor_differential_model import CpXorDifferentialModel sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher sage: from claasp.cipher_modules.models.utils import set_fixed_variables, integer_to_bit_list, write_model_to_file sage: speck = SpeckBlockCipher(block_bit_size=32, key_bit_size=64, number_of_rounds=4) - sage: cp = CpXorDifferentialTrailSearchModel(speck) + sage: cp = CpXorDifferentialModel(speck) sage: fixed_variables = [set_fixed_variables('key', 'equal', range(64), integer_to_bit_list(0, 64, 'little'))] sage: fixed_variables.append(set_fixed_variables('plaintext', 'equal', range(32), integer_to_bit_list(0, 32, 'little'))) sage: cp.build_xor_differential_trail_model(-1, fixed_variables) diff --git a/claasp/cipher_modules/models/cp/cp_models/cp_xor_differential_model.py b/claasp/cipher_modules/models/cp/cp_models/cp_xor_differential_model.py index 1c3494f0..0a52d543 100644 --- a/claasp/cipher_modules/models/cp/cp_models/cp_xor_differential_model.py +++ b/claasp/cipher_modules/models/cp/cp_models/cp_xor_differential_model.py @@ -116,7 +116,7 @@ def build_xor_differential_trail_model(self, weight=-1, fixed_variables=[]): sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher sage: speck = SpeckBlockCipher(block_bit_size=32, key_bit_size=64, number_of_rounds=4) sage: cp = CpXorDifferentialModel(speck) - sage: cp.build_xor_differential_trail_model(-1, fixed_variables) + sage: cp.build_xor_differential_trail_model() """ self.initialise_model() self.c = 0 @@ -338,12 +338,19 @@ def find_lowest_weight_xor_differential_trail(self, fixed_values=[], solver_name sage: speck = SpeckBlockCipher(number_of_rounds=5) sage: cp = CpXorDifferentialModel(speck) sage: cp.find_lowest_weight_xor_differential_trail(solver_name='Chuffed') # random - {'building_time': 0.007165431976318359, - 'cipher_id': 'speck_p32_k64_o32_r4', - 'components_values': {'cipher_output_4_12': {'value': '850a9520', - 'weight': 0}, + {'cipher': speck_p32_k64_o32_r5, + 'model_type': 'xor_differential_one_solution', + 'solver_name': 'Chuffed', + 'solving_time_seconds': 120.349, + 'memory_megabytes': 0.28, + 'components_values': {'plaintext': {'value': '28000010', 'weight': 0}, + 'key': {'value': '0000000000000000', 'weight': 0}, ... - 'total_weight': '9.0'} + 'cipher_output_4_12': {'value': '850a9520', 'weight': 0.0}}, + 'total_weight': '9.0', + 'status': 'SATISFIABLE', + 'building_time_seconds': 0.0021665096282958984, + 'test_name': 'find_lowest_weight_xor_differential_trail'} # related-key setting sage: from claasp.cipher_modules.models.cp.cp_models.cp_xor_differential_model import (CpXorDifferentialModel) @@ -386,7 +393,7 @@ def find_one_xor_differential_trail(self, fixed_values=[], solver_name=SOLVER_DE sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher sage: speck = SpeckBlockCipher(number_of_rounds=2) sage: cp = CpXorDifferentialModel(speck) - sage: cp.find_one_xor_differential_trail(solver_name=Chuffed') # random + sage: cp.find_one_xor_differential_trail(solver_name='Chuffed') # random {'cipher_id': 'speck_p32_k64_o32_r2', 'model_type': 'xor_differential_one_solution', ... diff --git a/claasp/cipher_modules/models/cp/cp_models/cp_xor_differential_number_of_active_sboxes_model.py b/claasp/cipher_modules/models/cp/cp_models/cp_xor_differential_number_of_active_sboxes_model.py index 2ee21fdb..0980c810 100644 --- a/claasp/cipher_modules/models/cp/cp_models/cp_xor_differential_number_of_active_sboxes_model.py +++ b/claasp/cipher_modules/models/cp/cp_models/cp_xor_differential_number_of_active_sboxes_model.py @@ -287,7 +287,7 @@ def get_xor_all_inputs(self, component1, component2): return all_inputs - def input_xor_differential_first_step_constraints(self, possible_sboxes): + def input_xor_differential_first_step_constraints(self, possible_sboxes=0): """ Return a list of CP constraints for the inputs of the cipher for the first step model. diff --git a/claasp/cipher_modules/models/cp/cp_models/cp_xor_differential_trail_search_fixing_number_of_active_sboxes_model.py b/claasp/cipher_modules/models/cp/cp_models/cp_xor_differential_trail_search_fixing_number_of_active_sboxes_model.py index c173ee33..21c8fd53 100644 --- a/claasp/cipher_modules/models/cp/cp_models/cp_xor_differential_trail_search_fixing_number_of_active_sboxes_model.py +++ b/claasp/cipher_modules/models/cp/cp_models/cp_xor_differential_trail_search_fixing_number_of_active_sboxes_model.py @@ -58,11 +58,11 @@ def build_xor_differential_trail_second_step_model(self, weight=-1, fixed_variab EXAMPLES:: sage: from claasp.cipher_modules.models.cp.cp_models.cp_xor_differential_trail_search_fixing_number_of_active_sboxes_model import ( - ....: CpXorDifferentialTrailSearchFixingNumberOfActiveSboxesModel) + ....: CpXorDifferentialFixingNumberOfActiveSboxesModel) sage: from claasp.ciphers.block_ciphers.aes_block_cipher import AESBlockCipher sage: from claasp.cipher_modules.models.utils import set_fixed_variables, integer_to_bit_list sage: aes = AESBlockCipher(number_of_rounds=2) - sage: cp = CpXorDifferentialTrailSearchFixingNumberOfActiveSboxesModel(aes) + sage: cp = CpXorDifferentialFixingNumberOfActiveSboxesModel(aes) sage: fixed_variables = [set_fixed_variables('key', 'not_equal', range(128), ....: integer_to_bit_list(0, 128, 'little'))] sage: cp.build_xor_differential_trail_second_step_model(-1, fixed_variables) @@ -98,17 +98,17 @@ def find_all_xor_differential_trails_with_fixed_weight(self, fixed_weight, fixed sage: from claasp.ciphers.block_ciphers.aes_block_cipher import AESBlockCipher sage: from claasp.cipher_modules.models.cp.cp_models.cp_xor_differential_trail_search_fixing_number_of_active_sboxes_model import ( - ....: CpXorDifferentialTrailSearchFixingNumberOfActiveSboxesModel) + ....: CpXorDifferentialFixingNumberOfActiveSboxesModel) sage: from claasp.cipher_modules.models.utils import set_fixed_variables, integer_to_bit_list sage: aes = AESBlockCipher(number_of_rounds=2) - sage: cp = CpXorDifferentialTrailSearchFixingNumberOfActiveSboxesModel(aes) + sage: cp = CpXorDifferentialFixingNumberOfActiveSboxesModel(aes) sage: fixed_variables = [set_fixed_variables('key', 'equal', range(128), ....: integer_to_bit_list(0, 128, 'little'))] sage: fixed_variables.append(set_fixed_variables('plaintext', 'not_equal', range(128), ....: integer_to_bit_list(0, 128, 'little'))) - sage: trails = cp.find_all_xor_differential_trails_with_fixed_weight(224, fixed_variables, 'Chuffed', 'Chuffed') # long + sage: trails = cp.find_all_xor_differential_trails_with_fixed_weight(224, fixed_variables, 'Chuffed', 'Chuffed') # long # doctest: +SKIP ... - sage: len(trails) # long + sage: len(trails) # long # doctest: +SKIP 8 """ return self.solve_full_two_steps_xor_differential_model('xor_differential_all_solutions', fixed_weight, fixed_values, first_step_solver_name, second_step_solver_name) @@ -135,19 +135,20 @@ def find_lowest_weight_xor_differential_trail(self, fixed_values=[], first_step_ sage: from claasp.ciphers.block_ciphers.aes_block_cipher import AESBlockCipher sage: from claasp.cipher_modules.models.cp.cp_models.cp_xor_differential_trail_search_fixing_number_of_active_sboxes_model import ( - ....: CpXorDifferentialTrailSearchFixingNumberOfActiveSboxesModel) + ....: CpXorDifferentialFixingNumberOfActiveSboxesModel) sage: from claasp.cipher_modules.models.utils import set_fixed_variables, integer_to_bit_list sage: aes = AESBlockCipher(number_of_rounds=2) - sage: cp = CpXorDifferentialTrailSearchFixingNumberOfActiveSboxesModel(aes) + sage: cp = CpXorDifferentialFixingNumberOfActiveSboxesModel(aes) sage: fixed_variables = [set_fixed_variables('key', 'equal', range(128), ....: integer_to_bit_list(0, 128, 'little'))] sage: fixed_variables.append(set_fixed_variables('plaintext', 'not_equal', range(128), ....: integer_to_bit_list(0, 128, 'little'))) sage: cp.find_lowest_weight_xor_differential_trail(fixed_variables, 'Chuffed', 'Chuffed') # random - {'cipher_id': 'aes_block_cipher_k128_p128_o128_r2', + 5 + {'cipher': 'aes_block_cipher_k128_p128_o128_r2', 'model_type': 'xor_differential', 'solver_name': 'Chuffed', - 'components_values': {'key': {'value': '0', 'weight': 0}, + 'components_values': {'key': {'value': '00000000000000000000000000000000', 'weight': 0}, ... 'total_weight': '30.0'} """ @@ -170,19 +171,19 @@ def find_one_xor_differential_trail(self, fixed_values=[], first_step_solver_nam sage: from claasp.ciphers.block_ciphers.aes_block_cipher import AESBlockCipher sage: from claasp.cipher_modules.models.cp.cp_models.cp_xor_differential_trail_search_fixing_number_of_active_sboxes_model import ( - ....: CpXorDifferentialTrailSearchFixingNumberOfActiveSboxesModel) + ....: CpXorDifferentialFixingNumberOfActiveSboxesModel) sage: from claasp.cipher_modules.models.utils import set_fixed_variables, integer_to_bit_list sage: aes = AESBlockCipher(number_of_rounds=2) - sage: cp = CpXorDifferentialTrailSearchFixingNumberOfActiveSboxesModel(aes) + sage: cp = CpXorDifferentialFixingNumberOfActiveSboxesModel(aes) sage: fixed_variables = [set_fixed_variables('key', 'equal', range(128), ....: integer_to_bit_list(0, 128, 'little'))] sage: fixed_variables.append(set_fixed_variables('plaintext', 'not_equal', range(128), ....: integer_to_bit_list(0, 128, 'little'))) sage: cp.find_one_xor_differential_trail(fixed_variables, 'Chuffed', 'Chuffed') # random - {'cipher_id': 'aes_block_cipher_k128_p128_o128_r2', + {'cipher': 'aes_block_cipher_k128_p128_o128_r2', 'model_type': 'xor_differential', ... - 'cipher_output_1_32':{'value': 'ffffffffffffffffffffffffffffffff', 'weight': 0}}, + 'cipher_output_1_32':{'value': 'ffffffffffffffffffffffffffffffff', 'weight': 0.0}}, 'total_weight': '224.0'} """ return self.solve_full_two_steps_xor_differential_model('xor_differential_one_solution', 0, fixed_values, first_step_solver_name, second_step_solver_name) @@ -205,16 +206,16 @@ def find_one_xor_differential_trail_with_fixed_weight(self, fixed_weight=-1, fix sage: from claasp.ciphers.block_ciphers.aes_block_cipher import AESBlockCipher sage: from claasp.cipher_modules.models.cp.cp_models.cp_xor_differential_trail_search_fixing_number_of_active_sboxes_model import ( - ....: CpXorDifferentialTrailSearchFixingNumberOfActiveSboxesModel) + ....: CpXorDifferentialFixingNumberOfActiveSboxesModel) sage: from claasp.cipher_modules.models.utils import set_fixed_variables, integer_to_bit_list sage: aes = AESBlockCipher(number_of_rounds=2) - sage: cp = CpXorDifferentialTrailSearchFixingNumberOfActiveSboxesModel(aes) + sage: cp = CpXorDifferentialFixingNumberOfActiveSboxesModel(aes) sage: fixed_variables = [set_fixed_variables('key', 'equal', range(128), ....: integer_to_bit_list(0, 128, 'little'))] sage: fixed_variables.append(set_fixed_variables('plaintext', 'not_equal', range(128), ....: integer_to_bit_list(0, 128, 'little'))) sage: cp.find_one_xor_differential_trail_with_fixed_weight(224, fixed_variables, 'Chuffed', 'Chuffed') # random - {'cipher_id': 'aes_block_cipher_k128_p128_o128_r2', + {'cipher': 'aes_block_cipher_k128_p128_o128_r2', 'model_type': 'xor_differential', 'solver_name': 'Chuffed', ... @@ -234,16 +235,16 @@ def generate_table_of_solutions(self, solution, solver_name): EXAMPLES:: sage: from claasp.cipher_modules.models.cp.cp_models.cp_xor_differential_trail_search_fixing_number_of_active_sboxes_model import ( - ....: CpXorDifferentialTrailSearchFixingNumberOfActiveSboxesModel) + ....: CpXorDifferentialFixingNumberOfActiveSboxesModel) sage: from claasp.ciphers.block_ciphers.aes_block_cipher import AESBlockCipher sage: from claasp.cipher_modules.models.utils import set_fixed_variables, integer_to_bit_list sage: aes = AESBlockCipher(number_of_rounds=2) - sage: cp = CpXorDifferentialTrailSearchFixingNumberOfActiveSboxesModel(aes) + sage: cp = CpXorDifferentialFixingNumberOfActiveSboxesModel(aes) sage: fixed_variables = [set_fixed_variables('key', 'not_equal', list(range(128)), ....: integer_to_bit_list(0, 128, 'little'))] sage: cp.build_xor_differential_trail_first_step_model(-1,fixed_variables) sage: first_step_solution, solve_time = cp.solve_model('xor_differential_first_step', 'Chuffed') - sage: cp.generate_table_of_solutions(first_step_solution) + sage: cp.generate_table_of_solutions(first_step_solution, 'Chuffed') """ cipher_name = self.cipher_id separator = '----------' @@ -290,9 +291,9 @@ def input_xor_differential_constraints(self): sage: from claasp.ciphers.block_ciphers.aes_block_cipher import AESBlockCipher sage: from claasp.cipher_modules.models.cp.cp_models.cp_xor_differential_trail_search_fixing_number_of_active_sboxes_model import ( - ....: CpXorDifferentialTrailSearchFixingNumberOfActiveSboxesModel) + ....: CpXorDifferentialFixingNumberOfActiveSboxesModel) sage: aes = AESBlockCipher(number_of_rounds=2) - sage: cp = CpXorDifferentialTrailSearchFixingNumberOfActiveSboxesModel(aes) + sage: cp = CpXorDifferentialFixingNumberOfActiveSboxesModel(aes) sage: cp.input_xor_differential_constraints() (['array[0..127] of var 0..1: key;', 'array[0..127] of var 0..1: plaintext;', @@ -326,18 +327,19 @@ def solve_full_two_steps_xor_differential_model(self, model_type='xor_differenti EXAMPLES:: sage: from claasp.cipher_modules.models.cp.cp_models.cp_xor_differential_trail_search_fixing_number_of_active_sboxes_model import ( - ....: CpXorDifferentialTrailSearchFixingNumberOfActiveSboxesModel) + ....: CpXorDifferentialFixingNumberOfActiveSboxesModel) sage: from claasp.ciphers.block_ciphers.aes_block_cipher import AESBlockCipher sage: from claasp.cipher_modules.models.utils import set_fixed_variables, integer_to_bit_list sage: aes = AESBlockCipher(number_of_rounds=2) - sage: cp = CpXorDifferentialTrailSearchFixingNumberOfActiveSboxesModel(aes) + sage: cp = CpXorDifferentialFixingNumberOfActiveSboxesModel(aes) sage: fixed_variables = [set_fixed_variables('key', 'not_equal', list(range(128)), ....: integer_to_bit_list(0, 128, 'little'))] sage: cp.solve_full_two_steps_xor_differential_model('xor_differential_one_solution', -1, fixed_variables, 'Chuffed', 'Chuffed') # random - {'building_time': 3.7489726543426514, - 'cipher_id': 'aes_block_cipher_k128_p128_o128_r2', + 1 + {'cipher': 'aes_block_cipher_k128_p128_o128_r2', ... - 'total_weight': '6'} + 'total_weight': '6.0', + 'building_time': 3.7489726543426514} """ possible_sboxes = 0 if weight > 0: @@ -435,11 +437,11 @@ def solve_model(self, model_type, solver_name=None): EXAMPLES:: sage: from claasp.cipher_modules.models.cp.cp_models.cp_xor_differential_trail_search_fixing_number_of_active_sboxes_model import ( - ....: CpXorDifferentialTrailSearchFixingNumberOfActiveSboxesModel) + ....: CpXorDifferentialFixingNumberOfActiveSboxesModel) sage: from claasp.ciphers.block_ciphers.aes_block_cipher import AESBlockCipher sage: from claasp.cipher_modules.models.utils import set_fixed_variables, integer_to_bit_list sage: aes = AESBlockCipher(number_of_rounds=2) - sage: cp = CpXorDifferentialTrailSearchFixingNumberOfActiveSboxesModel(aes) + sage: cp = CpXorDifferentialFixingNumberOfActiveSboxesModel(aes) sage: fixed_variables = [set_fixed_variables('key', 'not_equal', list(range(128)), ....: integer_to_bit_list(0, 128, 'little'))] sage: cp.build_xor_differential_trail_first_step_model(-1, fixed_variables) @@ -508,16 +510,17 @@ def transform_first_step_model(self, attempt, active_sboxes, weight=-1): EXAMPLES:: sage: from claasp.cipher_modules.models.cp.cp_models.cp_xor_differential_trail_search_fixing_number_of_active_sboxes_model import ( - ....: CpXorDifferentialTrailSearchFixingNumberOfActiveSboxesModel) + ....: CpXorDifferentialFixingNumberOfActiveSboxesModel) sage: from claasp.ciphers.block_ciphers.aes_block_cipher import AESBlockCipher sage: from claasp.cipher_modules.models.utils import set_fixed_variables, integer_to_bit_list sage: aes = AESBlockCipher(number_of_rounds=2) - sage: cp = CpXorDifferentialTrailSearchFixingNumberOfActiveSboxesModel(aes) + sage: cp = CpXorDifferentialFixingNumberOfActiveSboxesModel(aes) sage: fixed_variables = [set_fixed_variables('key', 'not_equal', range(128), ....: integer_to_bit_list(0, 128, 'little'))] sage: cp.build_xor_differential_trail_first_step_model(-1, fixed_variables) sage: first_step_solution, solve_time = cp.solve_model('xor_differential_first_step','Chuffed') sage: cp.transform_first_step_model(0, first_step_solution[0]) + 1 """ print(active_sboxes) self._first_step_find_all_solutions = [] diff --git a/claasp/cipher_modules/models/milp/milp_model.py b/claasp/cipher_modules/models/milp/milp_model.py index 9b384088..5b2b9726 100644 --- a/claasp/cipher_modules/models/milp/milp_model.py +++ b/claasp/cipher_modules/models/milp/milp_model.py @@ -226,7 +226,7 @@ def weight_constraints(self, weight, weight_precision=MILP_DEFAULT_WEIGHT_PRECIS sage: variables [('p[probability]', x_0)] sage: constraints - [x_0 == 100] + [x_0 == 1000] """ p = self._integer_variable variables = [] diff --git a/claasp/cipher_modules/models/milp/milp_models/milp_bitwise_deterministic_truncated_xor_differential_model.py b/claasp/cipher_modules/models/milp/milp_models/milp_bitwise_deterministic_truncated_xor_differential_model.py index 5eccd65e..7a8b8aae 100644 --- a/claasp/cipher_modules/models/milp/milp_models/milp_bitwise_deterministic_truncated_xor_differential_model.py +++ b/claasp/cipher_modules/models/milp/milp_models/milp_bitwise_deterministic_truncated_xor_differential_model.py @@ -195,10 +195,10 @@ def fix_variables_value_bitwise_deterministic_truncated_xor_differential_constra x_1 == 0, x_2 == 1, x_3 == 1, - x_6 <= 6 - 3*x_4 - 3*x_5, + x_5 <= 6 - 6*x_4, ... - -2 + 3*x_13 - 3*x_14 <= x_15, - x_4 + x_7 + x_10 + x_13 == 1] + -2 <= x_11, + x_4 + x_6 + x_8 + x_10 == 1] """ @@ -231,8 +231,8 @@ def link_binary_tuples_to_integer_variables(self, id_tuples, ids): sage: milp.init_model_in_sage_milp_class() sage: component = fancy.component_from(0, 6) sage: input_ids, output_ids = component._get_input_output_variables() - sage: _, input_id_tuples, output_id_tuples = component._get_input_output_variables_tuples(milp) - sage: constraints = milp.link_binary_tuples_to_integer_variables(input_id_tuples + output_id_tuples, input_ids + output_ids) + sage: input_ids_tuples, output_ids_tuples = component._get_input_output_variables_tuples() + sage: constraints = milp.link_binary_tuples_to_integer_variables(input_ids_tuples + output_ids_tuples, input_ids + output_ids) sage: constraints [x_96 == 2*x_0 + x_1, x_97 == 2*x_2 + x_3, diff --git a/claasp/cipher_modules/models/milp/milp_models/milp_bitwise_impossible_xor_differential_model.py b/claasp/cipher_modules/models/milp/milp_models/milp_bitwise_impossible_xor_differential_model.py index e9931a47..806c7275 100644 --- a/claasp/cipher_modules/models/milp/milp_models/milp_bitwise_impossible_xor_differential_model.py +++ b/claasp/cipher_modules/models/milp/milp_models/milp_bitwise_impossible_xor_differential_model.py @@ -313,23 +313,7 @@ def find_one_bitwise_impossible_xor_differential_trail(self, middle_round, fixed sage: plaintext = set_fixed_variables(component_id='plaintext', constraint_type='equal', bit_positions=range(48), bit_values=[0]*47 + [1]) sage: key = set_fixed_variables(component_id='key', constraint_type='equal', bit_positions=range(72), bit_values=[0]*72) sage: ciphertext = set_fixed_variables(component_id='cipher_output_11_12', constraint_type='equal', bit_positions=range(48), bit_values=[1]+[0]*16 + [2,0,0,0,2,2,2] + [0]*24) - sage: trail = milp.find_one_bitwise_impossible_xor_differential_trail(7, fixed_values=[plaintext, key, ciphertext]) - - # https://eprint.iacr.org/2016/490.pdf - # requires to comment the constraints that sum(inconsistent_vars) == 1 as we are considering half rounds not full rounds - sage: from claasp.cipher_modules.models.utils import integer_to_bit_list, set_fixed_variables - sage: from claasp.ciphers.permutations.ascon_sbox_sigma_permutation import AsconSboxSigmaPermutation - sage: ascon = AsconSboxSigmaPermutation(number_of_rounds=5) - sage: from claasp.cipher_modules.models.milp.milp_models.milp_bitwise_impossible_xor_differential_model import MilpBitwiseImpossibleXorDifferentialModel - sage: milp = MilpBitwiseImpossibleXorDifferentialModel(ascon) - sage: milp.init_model_in_sage_milp_class() - sage: plaintext = set_fixed_variables(component_id='plaintext', constraint_type='equal', bit_positions=range(320), bit_values=[1] + [0]*191 + [1] + [0]*63 + [1] + [0]*63 ) - sage: P1 = set_fixed_variables(component_id='intermediate_output_0_71', constraint_type='equal', bit_positions=range(320), bit_values= [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) - sage: P2 = set_fixed_variables(component_id='intermediate_output_1_71', constraint_type='equal', bit_positions=range(320), bit_values= [2, 2, 0, 2, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 0, 2, 2, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 2, 0, 2, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 2, 2, 0, 2, 0, 0, 2, 2, 0, 0, 2, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 2, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 2, 2, 0, 0, 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 2, 0, 2, 2, 2, 0, 2, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0]) - sage: P3 = set_fixed_variables(component_id='intermediate_output_2_71', constraint_type='equal', bit_positions=range(320), bit_values= [2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2]) - sage: P5 = set_fixed_variables(component_id='cipher_output_4_71', constraint_type='equal', bit_positions=range(320), bit_values= [0]*192 + [1] + [0]* 127) - sage: trail = milp.find_one_bitwise_impossible_xor_differential_trail(4, fixed_values=[plaintext, P1, P2, P3, P5]) - + sage: trail = milp.find_one_bitwise_impossible_xor_differential_trail(7, fixed_values=[plaintext, key, ciphertext]) # doctest: +SKIP """ start = time.time() @@ -382,7 +366,7 @@ def find_one_bitwise_impossible_xor_differential_trail_with_chosen_incompatible_ sage: P2 = set_fixed_variables(component_id='intermediate_output_1_71', constraint_type='equal', bit_positions=range(320), bit_values= [2, 2, 0, 2, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 0, 2, 2, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 2, 0, 2, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 2, 2, 0, 2, 0, 0, 2, 2, 0, 0, 2, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 2, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 2, 2, 0, 0, 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 2, 0, 2, 2, 2, 0, 2, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0]) sage: P3 = set_fixed_variables(component_id='intermediate_output_2_71', constraint_type='equal', bit_positions=range(320), bit_values= [2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2]) sage: P5 = set_fixed_variables(component_id='cipher_output_4_71', constraint_type='equal', bit_positions=range(320), bit_values= [0]*192 + [1] + [0]* 127) - sage: trail = milp.find_one_bitwise_impossible_xor_differential_trail_with_chosen_incompatible_components(["sbox_3_56"], fixed_values=[plaintext, P1, P2, P3, P5]) + sage: trail = milp.find_one_bitwise_impossible_xor_differential_trail_with_chosen_incompatible_components(["sbox_3_56"], fixed_values=[plaintext, P1, P2, P3, P5]) #doctest: +SKIP """ @@ -426,7 +410,7 @@ def find_one_bitwise_impossible_xor_differential_trail_with_fully_automatic_mode sage: key = set_fixed_variables(component_id='key', constraint_type='equal', bit_positions=range(64), bit_values=[0]*64) sage: key_backward = set_fixed_variables(component_id='key_backward', constraint_type='equal', bit_positions=range(64), bit_values=[0]*64) sage: ciphertext_backward = set_fixed_variables(component_id='cipher_output_10_13_backward', constraint_type='equal', bit_positions=range(32), bit_values=[0]*6 + [2,0,2] + [0]*23) - sage: trail = milp.find_one_bitwise_impossible_xor_differential_trail_with_fully_automatic_model(fixed_values=[plaintext, key, key_backward, ciphertext_backward]) + sage: trail = milp.find_one_bitwise_impossible_xor_differential_trail_with_fully_automatic_model(fixed_values=[plaintext, key, key_backward, ciphertext_backward]) # doctest: +SKIP sage: from claasp.cipher_modules.models.utils import integer_to_bit_list, set_fixed_variables @@ -436,7 +420,7 @@ def find_one_bitwise_impossible_xor_differential_trail_with_fully_automatic_mode sage: milp = MilpBitwiseImpossibleXorDifferentialModel(ascon) sage: milp.init_model_in_sage_milp_class() sage: P = set_fixed_variables(component_id='plaintext', constraint_type='equal', bit_positions=range(320), bit_values= [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ) - sage: trail = milp.find_one_bitwise_impossible_xor_differential_trail_with_fully_automatic_model(fixed_values=[P]) + sage: trail = milp.find_one_bitwise_impossible_xor_differential_trail_with_fully_automatic_model(fixed_values=[P]) # doctest: +SKIP """ start = time.time() diff --git a/claasp/cipher_modules/models/milp/milp_models/milp_wordwise_deterministic_truncated_xor_differential_model.py b/claasp/cipher_modules/models/milp/milp_models/milp_wordwise_deterministic_truncated_xor_differential_model.py index 34348713..823fb5bc 100644 --- a/claasp/cipher_modules/models/milp/milp_models/milp_wordwise_deterministic_truncated_xor_differential_model.py +++ b/claasp/cipher_modules/models/milp/milp_models/milp_wordwise_deterministic_truncated_xor_differential_model.py @@ -93,7 +93,7 @@ def add_constraints_to_build_in_sage_milp_class(self, fixed_bits=[], fixed_words sage: aes = AESBlockCipher(number_of_rounds=2) sage: milp = MilpWordwiseDeterministicTruncatedXorDifferentialModel(aes) sage: milp.init_model_in_sage_milp_class() - sage: milp.add_constraints_to_build_in_sage_milp_class() + sage: milp.add_constraints_to_build_in_sage_milp_class() # doctest: +SKIP """ self._verbose_print(MILP_BUILDING_MESSAGE) @@ -102,7 +102,6 @@ def add_constraints_to_build_in_sage_milp_class(self, fixed_bits=[], fixed_words x = self._binary_variable p = self._integer_variable - components = self._cipher.get_all_components() last_component = components[-1] @@ -112,9 +111,11 @@ def add_constraints_to_build_in_sage_milp_class(self, fixed_bits=[], fixed_words # objective is the number of unknown patterns i.e. tuples of the form (1, x) _, output_ids = last_component._get_wordwise_input_output_linked_class_tuples(self) - mip.add_constraint(p[MILP_TRUNCATED_XOR_DIFFERENTIAL_OBJECTIVE] == sum(x[output_msb] for output_msb in [id[0] for id in output_ids])) + mip.add_constraint(p[MILP_TRUNCATED_XOR_DIFFERENTIAL_OBJECTIVE] == sum( + x[output_msb] for output_msb in [id[0] for id in output_ids])) - def build_wordwise_deterministic_truncated_xor_differential_trail_model(self, fixed_bits=[], fixed_words=[], cipher_list=None): + def build_wordwise_deterministic_truncated_xor_differential_trail_model(self, fixed_bits=[], fixed_words=[], + cipher_list=None): """ Build the model for the search of wordwise deterministic truncated XOR differential trails. @@ -138,18 +139,19 @@ def build_wordwise_deterministic_truncated_xor_differential_trail_model(self, fi sage: milp = MilpWordwiseDeterministicTruncatedXorDifferentialModel(aes) sage: milp.init_model_in_sage_milp_class() sage: from claasp.cipher_modules.models.utils import integer_to_bit_list, set_fixed_variables - sage: plaintext = set_fixed_variables(component_id='plaintext', constraint_type='equal', bit_positions=range(16), - bit_values=[0, 1, 0, 3] + [0] * 12) - sage: key = set_fixed_variables(component_id='key', constraint_type='equal', bit_positions=range(128), - bit_values=[0] * 128) - sage: milp.build_wordwise_deterministic_truncated_xor_differential_trail_model(fixed_bits=[key], fixed_words=[plaintext]) + sage: plaintext = set_fixed_variables(component_id='plaintext', constraint_type='equal', bit_positions=range(16), bit_values=[0, 1, 0, 3] + [0] * 12) + sage: key = set_fixed_variables(component_id='key', constraint_type='equal', bit_positions=range(128), bit_values=[0] * 128) + sage: milp.build_wordwise_deterministic_truncated_xor_differential_trail_model(fixed_bits=[key], fixed_words=[plaintext]) # doctest: +SKIP ... """ self._variables_list = [] cipher_list = cipher_list or [self._cipher] - component_list = [c for cipher_component in [cipher.get_all_components() for cipher in cipher_list] for c in cipher_component] - variables, constraints = self.input_wordwise_deterministic_truncated_xor_differential_constraints(component_list) - constraints += self.fix_variables_value_wordwise_deterministic_truncated_xor_differential_constraints(fixed_bits, fixed_words, cipher_list) + component_list = [c for cipher_component in [cipher.get_all_components() for cipher in cipher_list] for c in + cipher_component] + variables, constraints = self.input_wordwise_deterministic_truncated_xor_differential_constraints( + component_list) + constraints += self.fix_variables_value_wordwise_deterministic_truncated_xor_differential_constraints( + fixed_bits, fixed_words, cipher_list) self._model_constraints = constraints for component in component_list: @@ -159,14 +161,17 @@ def build_wordwise_deterministic_truncated_xor_differential_trail_model(self, fi operation_types = ['AND', 'MODADD', 'MODSUB', 'NOT', 'OR', 'ROTATE', 'SHIFT', 'XOR'] if component.type in component_types or operation in operation_types: - variables, constraints = component.milp_wordwise_deterministic_truncated_xor_differential_constraints(self) + variables, constraints = component.milp_wordwise_deterministic_truncated_xor_differential_constraints( + self) else: print(f'{component.id} not yet implemented') self._variables_list.extend(variables) self._model_constraints.extend(constraints) - def fix_variables_value_wordwise_deterministic_truncated_xor_differential_constraints(self, fixed_bits=[], fixed_words=[], cipher_list=None): + def fix_variables_value_wordwise_deterministic_truncated_xor_differential_constraints(self, fixed_bits=[], + fixed_words=[], + cipher_list=None): """ Returns a list of constraints that fix the input variables to a specific value. @@ -218,7 +223,8 @@ def fix_variables_value_wordwise_deterministic_truncated_xor_differential_constr for fixed_variable in fixed_bits: if fixed_variable["constraint_type"] == "equal": output_bit_size = get_output_bit_size_from_id(cipher_list, fixed_variable["component_id"]) - for i, current_word_bits in enumerate(array_split(range(output_bit_size), output_bit_size // self._word_size)): + for i, current_word_bits in enumerate( + array_split(range(output_bit_size), output_bit_size // self._word_size)): if set(current_word_bits) <= set(fixed_variable["bit_positions"]): if sum([fixed_variable["bit_values"][fixed_variable["bit_positions"].index(_)] for _ in current_word_bits]) == 0: @@ -240,18 +246,19 @@ def input_wordwise_deterministic_truncated_xor_differential_constraints(self, co sage: milp = MilpWordwiseDeterministicTruncatedXorDifferentialModel(cipher) sage: milp.init_model_in_sage_milp_class() sage: variables, constraints = milp.input_wordwise_deterministic_truncated_xor_differential_constraints() - sage: variables - ('x[xor_0_36_11]', x_1571), - ('x[xor_0_36_12]', x_1572), + ... + sage: variables # doctest: +SKIP + ('x_class[key_word_0_class]', x_480), + ('x_class[key_word_1_class]', x_481), ... ('x[cipher_output_1_32_126]', x_3078), ('x[cipher_output_1_32_127]', x_3079)] - sage: constraints + sage: constraints # doctest: +SKIP [1 <= 1 + x_0 - x_1 + x_2 + x_3 + x_4 + x_5 + x_6 + x_7 + x_8 + x_9, 1 <= 1 + x_1 - x_9, ... - x_2918 == 2*x_3060 + x_3061, - x_2919 == 2*x_3070 + x_3071] + x_3078 == 2*x_3044 + x_3045, + x_3079 == 2*x_3054 + x_3055] """ @@ -282,7 +289,7 @@ def input_wordwise_deterministic_truncated_xor_differential_constraints(self, co constraints.extend(minimized_constraints) variables.extend([(f"x_class[{var}]", x_class[var]) for var in all_int_vars] + \ - [(f"x[{var}]", x[var]) for var in all_vars]) + [(f"x[{var}]", x[var]) for var in all_vars]) # link class tuple (c0, c1) to the integer value of the class (0, 1, 2, 3) input_tuples, output_tuples = component._get_wordwise_input_output_linked_class_tuples(self) @@ -294,7 +301,9 @@ def input_wordwise_deterministic_truncated_xor_differential_constraints(self, co return variables, constraints - def find_one_wordwise_deterministic_truncated_xor_differential_trail(self, fixed_bits=[], fixed_words=[], solver_name=SOLVER_DEFAULT, external_solver_name=None): + def find_one_wordwise_deterministic_truncated_xor_differential_trail(self, fixed_bits=[], fixed_words=[], + solver_name=SOLVER_DEFAULT, + external_solver_name=None): """ Returns one deterministic truncated XOR differential trail. @@ -316,9 +325,9 @@ def find_one_wordwise_deterministic_truncated_xor_differential_trail(self, fixed sage: M = MilpWordwiseDeterministicTruncatedXorDifferentialModel(aes) sage: plaintext = set_fixed_variables(component_id='plaintext', constraint_type='equal', bit_positions=range(16), bit_values=[0,1,0,3] + [0] * 12) sage: key = set_fixed_variables(component_id='key', constraint_type='equal', bit_positions=range(128), bit_values=[0]*128) - sage: trail = M.find_one_wordwise_deterministic_truncated_xor_differential_trail(fixed_bits=[key], fixed_words=[plaintext]) + sage: trail = M.find_one_wordwise_deterministic_truncated_xor_differential_trail(fixed_bits=[key], fixed_words=[plaintext]) # doctest: +SKIP ... - sage: trail['status'] + sage: trail['status'] # doctest: +SKIP 'SATISFIABLE' """ start = time.time() @@ -334,7 +343,10 @@ def find_one_wordwise_deterministic_truncated_xor_differential_trail(self, fixed return solution - def find_lowest_varied_patterns_wordwise_deterministic_truncated_xor_differential_trail(self, fixed_bits=[], fixed_words=[], solver_name=SOLVER_DEFAULT, external_solver_name=None): + def find_lowest_varied_patterns_wordwise_deterministic_truncated_xor_differential_trail(self, fixed_bits=[], + fixed_words=[], + solver_name=SOLVER_DEFAULT, + external_solver_name=None): """ Return the solution representing a differential trail with the lowest number of unknown variables. @@ -355,7 +367,7 @@ def find_lowest_varied_patterns_wordwise_deterministic_truncated_xor_differentia sage: M.init_model_in_sage_milp_class() sage: trail = M.find_lowest_varied_patterns_wordwise_deterministic_truncated_xor_differential_trail(get_single_key_scenario_format_for_fixed_values(aes)) # doctest: +SKIP ... - sage: trail['total_weight'] + sage: trail['total_weight'] # doctest: +SKIP 4.0 @@ -376,7 +388,6 @@ def find_lowest_varied_patterns_wordwise_deterministic_truncated_xor_differentia return solution - @property def trunc_wordvar(self): return self._trunc_wordvar @@ -385,7 +396,6 @@ def trunc_wordvar(self): def word_size(self): return self._word_size - def _get_component_values(self, objective_variables, components_variables): components_values = {} list_component_ids = self._cipher.inputs + self._cipher.get_all_components_ids() @@ -393,6 +403,7 @@ def _get_component_values(self, objective_variables, components_variables): dict_tmp = self._get_component_value_weight(component_id, components_variables) components_values[component_id] = dict_tmp return components_values + def _parse_solver_output(self): mip = self._model components_variables = mip.get_values(self._trunc_wordvar) @@ -421,7 +432,7 @@ def _get_final_output(self, component_id, components_variables, suffix_dict): final_output = [] for suffix in suffix_dict.keys(): diff_str = _get_variables_values_as_string(component_id + "_word", components_variables, suffix, - suffix_dict[suffix]) + suffix_dict[suffix]) final_output.append(set_component_solution(diff_str)) - return final_output \ No newline at end of file + return final_output diff --git a/claasp/cipher_modules/models/milp/milp_models/milp_wordwise_impossible_xor_differential_model.py b/claasp/cipher_modules/models/milp/milp_models/milp_wordwise_impossible_xor_differential_model.py index 7c3a4a37..7488f281 100644 --- a/claasp/cipher_modules/models/milp/milp_models/milp_wordwise_impossible_xor_differential_model.py +++ b/claasp/cipher_modules/models/milp/milp_models/milp_wordwise_impossible_xor_differential_model.py @@ -59,7 +59,7 @@ def build_wordwise_impossible_xor_differential_trail_model(self, fixed_bits=[], sage: milp._forward_cipher = aes.get_partial_cipher(0, 0, keep_key_schedule=True) sage: backward_cipher = milp._cipher.cipher_partial_inverse(1, 1, keep_key_schedule=False) sage: milp._backward_cipher = backward_cipher.add_suffix_to_components("_backward", [backward_cipher.get_all_components_ids()[-1]]) - sage: milp.build_wordwise_impossible_xor_differential_trail_model() + sage: milp.build_wordwise_impossible_xor_differential_trail_model() # doctest: +SKIP ... """ cipher_list = [self._forward_cipher, self._backward_cipher] @@ -88,7 +88,7 @@ def add_constraints_to_build_in_sage_milp_class(self, middle_round=None, fixed_b sage: from claasp.cipher_modules.models.milp.milp_models.milp_wordwise_impossible_xor_differential_model import MilpWordwiseImpossibleXorDifferentialModel sage: milp = MilpWordwiseImpossibleXorDifferentialModel(aes) sage: milp.init_model_in_sage_milp_class() - sage: milp.add_constraints_to_build_in_sage_milp_class(1, get_single_key_scenario_format_for_fixed_values(aes)) + sage: milp.add_constraints_to_build_in_sage_milp_class(1, get_single_key_scenario_format_for_fixed_values(aes)) # doctest: +SKIP """ self._verbose_print(MILP_BUILDING_MESSAGE) @@ -168,7 +168,7 @@ def add_constraints_to_build_in_sage_milp_class_with_chosen_incompatible_compone sage: from claasp.cipher_modules.models.milp.milp_models.milp_wordwise_impossible_xor_differential_model import MilpWordwiseImpossibleXorDifferentialModel sage: milp = MilpWordwiseImpossibleXorDifferentialModel(aes) sage: milp.init_model_in_sage_milp_class() - sage: milp.add_constraints_to_build_in_sage_milp_class_with_fixed_components(["intermediate_output_0_37"], get_single_key_scenario_format_for_fixed_values(aes)) + sage: milp.add_constraints_to_build_in_sage_milp_class_with_chosen_incompatible_components(["intermediate_output_0_37"], get_single_key_scenario_format_for_fixed_values(aes)) # doctest: +SKIP """ self._verbose_print(MILP_BUILDING_MESSAGE) @@ -273,7 +273,7 @@ def add_constraints_to_build_fully_automatic_model_in_sage_milp_class(self, fixe sage: from claasp.cipher_modules.models.milp.milp_models.milp_wordwise_impossible_xor_differential_model import MilpWordwiseImpossibleXorDifferentialModel sage: milp = MilpWordwiseImpossibleXorDifferentialModel(aes) sage: milp.init_model_in_sage_milp_class() - sage: milp.add_constraints_to_build_fully_automatic_model_in_sage_milp_class(get_single_key_scenario_format_for_fixed_values(aes)) + sage: milp.add_constraints_to_build_fully_automatic_model_in_sage_milp_class(get_single_key_scenario_format_for_fixed_values(aes)) # doctest: +SKIP """ self._verbose_print(MILP_BUILDING_MESSAGE) @@ -326,7 +326,7 @@ def find_one_wordwise_impossible_xor_differential_trail(self, middle_round=None, sage: aes = AESBlockCipher(number_of_rounds=2) sage: from claasp.cipher_modules.models.milp.milp_models.milp_wordwise_impossible_xor_differential_model import MilpWordwiseImpossibleXorDifferentialModel sage: milp = MilpWordwiseImpossibleXorDifferentialModel(aes) - sage: trail = milp.find_one_wordwise_impossible_xor_differential_trail(1, get_single_key_scenario_format_for_fixed_values(aes)) + sage: trail = milp.find_one_wordwise_impossible_xor_differential_trail(1, get_single_key_scenario_format_for_fixed_values(aes)) # doctest: +SKIP """ start = time.time() @@ -361,7 +361,7 @@ def find_one_wordwise_impossible_xor_differential_trail_with_chosen_components(s sage: aes = AESBlockCipher(number_of_rounds=2) sage: from claasp.cipher_modules.models.milp.milp_models.milp_wordwise_impossible_xor_differential_model import MilpWordwiseImpossibleXorDifferentialModel sage: milp = MilpWordwiseImpossibleXorDifferentialModel(aes) - sage: trail = milp.find_one_wordwise_impossible_xor_differential_trail_with_chosen_components(['mix_column_0_21'], get_single_key_scenario_format_for_fixed_values(aes)) + sage: trail = milp.find_one_wordwise_impossible_xor_differential_trail_with_chosen_components(['mix_column_0_21'], get_single_key_scenario_format_for_fixed_values(aes)) # doctest: +SKIP """ start = time.time() @@ -398,7 +398,7 @@ def find_one_wordwise_impossible_xor_differential_trail_with_fully_automatic_mod sage: aes = AESBlockCipher(number_of_rounds=2) sage: from claasp.cipher_modules.models.milp.milp_models.milp_wordwise_impossible_xor_differential_model import MilpWordwiseImpossibleXorDifferentialModel sage: milp = MilpWordwiseImpossibleXorDifferentialModel(aes) - sage: trail = milp.find_one_wordwise_impossible_xor_differential_trail_with_fully_automatic_model(get_single_key_scenario_format_for_fixed_values(aes)) + sage: trail = milp.find_one_wordwise_impossible_xor_differential_trail_with_fully_automatic_model(get_single_key_scenario_format_for_fixed_values(aes)) # doctest: +SKIP """ start = time.time() diff --git a/claasp/cipher_modules/models/milp/milp_models/milp_xor_differential_model.py b/claasp/cipher_modules/models/milp/milp_models/milp_xor_differential_model.py index 1d21f917..4cb3d0a9 100644 --- a/claasp/cipher_modules/models/milp/milp_models/milp_xor_differential_model.py +++ b/claasp/cipher_modules/models/milp/milp_models/milp_xor_differential_model.py @@ -69,7 +69,7 @@ def add_constraints_to_build_in_sage_milp_class(self, weight=-1, weight_precisio ... sage: mip = milp._model sage: mip.number_of_variables() - 468 + 532 """ self._verbose_print(MILP_BUILDING_MESSAGE) self._weight_precision = weight_precision @@ -161,9 +161,9 @@ def find_all_xor_differential_trails_with_fixed_weight(self, fixed_weight, fixed sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher sage: speck = SpeckBlockCipher(number_of_rounds=5) sage: milp = MilpXorDifferentialModel(speck) - sage: trails = milp.find_all_xor_differential_trails_with_fixed_weight(9) # long + sage: trails = milp.find_all_xor_differential_trails_with_fixed_weight(9) # long # doctest: +SKIP ... - sage: len(trails) + sage: len(trails) # doctest: +SKIP 2 # related-key setting @@ -173,9 +173,9 @@ def find_all_xor_differential_trails_with_fixed_weight(self, fixed_weight, fixed sage: speck = SpeckBlockCipher(number_of_rounds=5) sage: milp = MilpXorDifferentialModel(speck) sage: key = set_fixed_variables('key', 'not_equal', list(range(64)), [0] * 64) - sage: trails = milp.find_all_xor_differential_trails_with_fixed_weight(2, fixed_values=[key]) # long + sage: trails = milp.find_all_xor_differential_trails_with_fixed_weight(2, fixed_values=[key])#long# doctest: +SKIP ... - sage: len(trails) + sage: len(trails) # doctest: +SKIP 2 """ start = time.time() @@ -304,7 +304,7 @@ def exclude_variables_value_constraints(self, fixed_variables=[]): return constraints - def is_single_key(self, fixed_values): + def is_single_key(self, fixed_values=[]): """ Return True if key is fixed to 0, False otherwise. @@ -314,11 +314,12 @@ def is_single_key(self, fixed_values): be fixed EXAMPLES:: - from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher + sage: from claasp.cipher_modules.models.utils import get_single_key_scenario_format_for_fixed_values + sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher sage: from claasp.cipher_modules.models.milp.milp_models.milp_xor_differential_model import MilpXorDifferentialModel sage: speck = SpeckBlockCipher(block_bit_size=8, key_bit_size=16, number_of_rounds=2) sage: milp = MilpXorDifferentialModel(speck) - sage: milp.is_single_key(speck) + sage: milp.is_single_key(get_single_key_scenario_format_for_fixed_values(speck)) True """ cipher_inputs = self._cipher.inputs @@ -366,9 +367,9 @@ def find_all_xor_differential_trails_with_weight_at_most(self, min_weight, max_w sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher sage: speck = SpeckBlockCipher(number_of_rounds=5) sage: milp = MilpXorDifferentialModel(speck) - sage: trails = milp.find_all_xor_differential_trails_with_weight_at_most(9, 10) # long + sage: trails = milp.find_all_xor_differential_trails_with_weight_at_most(9, 10) # long #doctest: +SKIP ... - sage: len(trails) + sage: len(trails) #doctest: +SKIP 28 # related-key setting @@ -378,9 +379,9 @@ def find_all_xor_differential_trails_with_weight_at_most(self, min_weight, max_w sage: speck = SpeckBlockCipher(number_of_rounds=5) sage: milp = MilpXorDifferentialModel(speck) sage: key = set_fixed_variables('key', 'not_equal', list(range(64)), [0] * 64) - sage: trails = milp.find_all_xor_differential_trails_with_weight_at_most(2, 3, fixed_values=[key]) # long + sage: trails = milp.find_all_xor_differential_trails_with_weight_at_most(2, 3, fixed_values=[key]) # long #doctest: +SKIP ... - sage: len(trails) + sage: len(trails) #doctest: +SKIP 9 """ start = time.time() @@ -454,13 +455,13 @@ def find_lowest_weight_xor_differential_trail(self, fixed_values=[], weight_prec EXAMPLES:: # single-key setting - from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher + sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher sage: from claasp.cipher_modules.models.milp.milp_models.milp_xor_differential_model import MilpXorDifferentialModel sage: speck = SpeckBlockCipher(number_of_rounds=5) sage: milp = MilpXorDifferentialModel(speck) - sage: trail = milp.find_lowest_weight_xor_differential_trail() + sage: trail = milp.find_lowest_weight_xor_differential_trail() #doctest: +SKIP ... - sage: trail["total_weight"] + sage: trail["total_weight"] #doctest: +SKIP 9.0 # related-key setting @@ -470,9 +471,9 @@ def find_lowest_weight_xor_differential_trail(self, fixed_values=[], weight_prec sage: speck = SpeckBlockCipher(number_of_rounds=5) sage: milp = MilpXorDifferentialModel(speck) sage: key = set_fixed_variables('key', 'not_equal', list(range(64)), [0] * 64) - sage: trail = milp.find_lowest_weight_xor_differential_trail(fixed_values=[key]) + sage: trail = milp.find_lowest_weight_xor_differential_trail(fixed_values=[key]) #doctest: +SKIP ... - sage: trail["total_weight"] + sage: trail["total_weight"] #doctest: +SKIP 1.0 """ start = time.time() @@ -515,7 +516,7 @@ def find_one_xor_differential_trail(self, fixed_values=[], weight_precision=MILP sage: from claasp.cipher_modules.models.milp.milp_models.milp_xor_differential_model import MilpXorDifferentialModel sage: speck = SpeckBlockCipher(number_of_rounds=5) sage: milp = MilpXorDifferentialModel(speck) - sage: trail = milp.find_one_xor_differential_trail() # random + sage: trail = milp.find_one_xor_differential_trail() # random # doctest: +SKIP # related-key setting sage: from claasp.cipher_modules.models.utils import set_fixed_variables @@ -524,7 +525,7 @@ def find_one_xor_differential_trail(self, fixed_values=[], weight_precision=MILP sage: speck = SpeckBlockCipher(number_of_rounds=5) sage: milp = MilpXorDifferentialModel(speck) sage: key = set_fixed_variables('key', 'not_equal', list(range(64)), [0] * 64) - sage: trail = milp.find_one_xor_differential_trail(fixed_values=[key]) # random + sage: trail = milp.find_one_xor_differential_trail(fixed_values=[key]) # random # doctest: +SKIP """ start = time.time() self.init_model_in_sage_milp_class(solver_name) @@ -562,12 +563,12 @@ def find_one_xor_differential_trail_with_fixed_weight(self, fixed_weight, fixed_ EXAMPLES:: # single-key setting - from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher + sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher sage: from claasp.cipher_modules.models.milp.milp_models.milp_xor_differential_model import MilpXorDifferentialModel sage: speck = SpeckBlockCipher(number_of_rounds=3) sage: milp = MilpXorDifferentialModel(speck) - sage: trail = milp.find_one_xor_differential_trail_with_fixed_weight(3) # random - sage: trail['total_weight'] + sage: trail = milp.find_one_xor_differential_trail_with_fixed_weight(3) # random # doctest: +SKIP + sage: trail['total_weight'] # doctest: +SKIP 3.0 # related-key setting @@ -577,8 +578,8 @@ def find_one_xor_differential_trail_with_fixed_weight(self, fixed_weight, fixed_ sage: speck = SpeckBlockCipher(number_of_rounds=3) sage: milp = MilpXorDifferentialModel(speck) sage: key = set_fixed_variables('key', 'not_equal', list(range(64)), [0] * 64) - sage: trail = milp.find_one_xor_differential_trail_with_fixed_weight(3, fixed_values=[key]) # random - sage: trail['total_weight'] + sage: trail = milp.find_one_xor_differential_trail_with_fixed_weight(3, fixed_values=[key]) # random # doctest: +SKIP + sage: trail['total_weight'] # doctest: +SKIP 3.0 """ start = time.time() diff --git a/claasp/cipher_modules/models/milp/milp_models/milp_xor_linear_model.py b/claasp/cipher_modules/models/milp/milp_models/milp_xor_linear_model.py index 717ab946..4f35dd32 100644 --- a/claasp/cipher_modules/models/milp/milp_models/milp_xor_linear_model.py +++ b/claasp/cipher_modules/models/milp/milp_models/milp_xor_linear_model.py @@ -74,7 +74,7 @@ def add_constraints_to_build_in_sage_milp_class(self, weight=-1, weight_precisio ... sage: mip = milp._model sage: mip.number_of_variables() - 1018 + 743 """ self._verbose_print(MILP_BUILDING_MESSAGE) self._weight_precision = weight_precision @@ -301,9 +301,9 @@ def find_all_xor_linear_trails_with_fixed_weight(self, fixed_weight, fixed_value sage: speck = SpeckBlockCipher(block_bit_size=8, key_bit_size=16, number_of_rounds=4) sage: milp = MilpXorLinearModel(speck) sage: key = set_fixed_variables('key', 'not_equal', list(range(16)), [0] * 16) - sage: trails = milp.find_all_xor_linear_trails_with_fixed_weight(2, fixed_values=[key]) # long + sage: trails = milp.find_all_xor_linear_trails_with_fixed_weight(2, fixed_values=[key]) # long # doctest: +SKIP ... - sage: len(trails) + sage: len(trails) # doctest: +SKIP 8 """ start = time.time() @@ -399,9 +399,9 @@ def find_all_xor_linear_trails_with_weight_at_most(self, min_weight, max_weight, sage: speck = SpeckBlockCipher(block_bit_size=8, key_bit_size=16, number_of_rounds=4) sage: milp = MilpXorLinearModel(speck) sage: key = set_fixed_variables('key', 'not_equal', list(range(16)), [0] * 16) - sage: trails = milp.find_all_xor_linear_trails_with_weight_at_most(0, 3, fixed_values=[key]) # long + sage: trails = milp.find_all_xor_linear_trails_with_weight_at_most(0, 3, fixed_values=[key]) # long # doctest: +SKIP ... - sage: len(trails) + sage: len(trails) # doctest: +SKIP 73 """ start = time.time() @@ -504,8 +504,8 @@ def find_lowest_weight_xor_linear_trail(self, fixed_values=[], weight_precision= sage: speck = SpeckBlockCipher(block_bit_size=16, key_bit_size=32, number_of_rounds=4) sage: milp = MilpXorLinearModel(speck) sage: key = set_fixed_variables('key', 'not_equal', list(range(32)), [0] * 32) - sage: trail = milp.find_lowest_weight_xor_linear_trail(fixed_values=[key]) - sage: trail["total_weight"] + sage: trail = milp.find_lowest_weight_xor_linear_trail(fixed_values=[key]) # doctest: +SKIP + sage: trail["total_weight"] # doctest: +SKIP 3.0 """ start = time.time() @@ -744,7 +744,7 @@ def update_xor_linear_constraints_for_more_than_two_bits(self, constraints, inpu constraint += x[output_var] constraints.append(constraint >= 1) - def weight_xor_linear_constraints(self, weight, weight_precision): + def weight_xor_linear_constraints(self, weight, weight_precision=MILP_DEFAULT_WEIGHT_PRECISION): """ Return a list of variables and a list of constraints that fix the total weight to a specific value. By default, the weight corresponds to the negative base-2 logarithm of the correlation of the trail. @@ -766,7 +766,7 @@ def weight_xor_linear_constraints(self, weight, weight_precision): sage: variables [('p[probability]', x_0)] sage: constraints - [x_0 == 100] + [x_0 == 1000] """ return self.weight_constraints(weight, weight_precision) diff --git a/claasp/cipher_modules/models/milp/utils/dictionary_containing_truncated_xor_inequalities_between_n_input_bits.obj b/claasp/cipher_modules/models/milp/utils/dictionary_containing_truncated_xor_inequalities_between_n_input_bits.obj index 096790f8..6a493584 100644 Binary files a/claasp/cipher_modules/models/milp/utils/dictionary_containing_truncated_xor_inequalities_between_n_input_bits.obj and b/claasp/cipher_modules/models/milp/utils/dictionary_containing_truncated_xor_inequalities_between_n_input_bits.obj differ diff --git a/claasp/cipher_modules/models/milp/utils/generate_inequalities_for_wordwise_truncated_xor_with_n_input_bits.py b/claasp/cipher_modules/models/milp/utils/generate_inequalities_for_wordwise_truncated_xor_with_n_input_bits.py index 66e61033..fe9f80f8 100644 --- a/claasp/cipher_modules/models/milp/utils/generate_inequalities_for_wordwise_truncated_xor_with_n_input_bits.py +++ b/claasp/cipher_modules/models/milp/utils/generate_inequalities_for_wordwise_truncated_xor_with_n_input_bits.py @@ -100,6 +100,7 @@ def get_valid_points_for_wordwise_xor(delta_in_1, zeta_in_1, delta_in_2, zeta_in zeta_out = 0 if delta_in_1 + delta_in_2 > 2: delta_out = 3 + zeta_out = -2 elif delta_in_1 + delta_in_2 == 1: delta_out = 1 zeta_out = zeta_in_1 + zeta_in_2 @@ -107,6 +108,7 @@ def get_valid_points_for_wordwise_xor(delta_in_1, zeta_in_1, delta_in_2, zeta_in delta_out = 0 elif zeta_in_1 + zeta_in_2 < 0: delta_out = 2 + zeta_out = -1 elif zeta_in_1 == zeta_in_2: delta_out = 0 else: @@ -169,6 +171,7 @@ def generate_valid_points_for_xor_between_n_input_words(wordsize=4, number_of_wo zeta[summand + 1]) delta_output, zeta_output = get_valid_points_for_wordwise_xor(tmp_delta[-1], tmp_zeta[-1], delta[-1], zeta[-1]) + zeta_output = max(0, zeta_output) if delta.count(3) == 0 and delta.count(2) == 1 and delta.count(1) > 1: only_fixed_patterns = [i[1] for i in enumerate(zeta) if delta[i[0]] == 1] if len(only_fixed_patterns) > 1: diff --git a/claasp/cipher_modules/models/milp/utils/utils.py b/claasp/cipher_modules/models/milp/utils/utils.py index 266633cd..dd288c05 100644 --- a/claasp/cipher_modules/models/milp/utils/utils.py +++ b/claasp/cipher_modules/models/milp/utils/utils.py @@ -131,6 +131,19 @@ def generate_espresso_input(valid_points): def 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) + ... + + """ espresso_input = generate_espresso_input(valid_points) espresso_process = run(['espresso', '-epos', '-okiss'], input=espresso_input, @@ -164,6 +177,7 @@ def milp_less(model, a, b, big_m): 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) @@ -172,10 +186,14 @@ def milp_less(model, a, b, big_m): 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 = M.milp_less(M, a, b, big_m) + 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] + """ d = model.binary_variable a_less_b = d[str(a) + "_less_" + str(b) + "_dummy"] @@ -252,6 +270,7 @@ def milp_generalized_and(model, var_list): 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) @@ -259,10 +278,18 @@ def milp_generalized_and(model, var_list): sage: mip = M._model sage: d = M._binary_variable sage: var_list = [d[i] for i in range(4)] - sage: general_and, constraints = M.milp_generalized_and(var_list) + 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] + """ d = model.binary_variable @@ -287,6 +314,7 @@ def milp_eq(model, a, b, big_m): 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) @@ -294,10 +322,19 @@ def milp_eq(model, a, b, big_m): 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 = M.milp_eq(M, a, b, big_m) + 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] """ constraints = [] @@ -319,6 +356,7 @@ def milp_neq(model, a, b, big_m): 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) @@ -326,9 +364,19 @@ def milp_neq(model, a, b, big_m): 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 = M.milp_neq(M, a, b, big_m) + 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] """ constraints = [] @@ -349,6 +397,7 @@ def milp_xor(a, b, c): 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) @@ -356,9 +405,10 @@ def milp_xor(a, b, c): sage: mip = M._model sage: x = M._binary_variable sage: a = x[0]; b = x[1]; c = x[2] - sage: for i in M.milp_xor(M,a,b,c): + sage: for i in milp_xor(a,b,c): ....: mip.add_constraint(i) - ... + sage: a + x_0 """ constraints = [a + b >= c, a + c >= b, @@ -374,7 +424,7 @@ def milp_generalized_xor(input_var_list, output_bit): EXAMPLES:: - sage: from claasp.cipher_modules.models.milp.utils import utils + 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 @@ -383,9 +433,11 @@ def milp_generalized_xor(input_var_list, output_bit): 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 utils.milp_generalized_xor(M, var_list, b): + sage: for i in milp_generalized_xor(var_list, b): ....: mip.add_constraint(i) ... + sage: var_list + [x_0, x_1] """ constraints = [] number_of_inputs = len(input_var_list) @@ -544,6 +596,7 @@ def milp_xor_truncated(model, input_1, input_2, output): 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) @@ -560,7 +613,7 @@ def milp_xor_truncated(model, input_1, input_2, output): def 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 words + 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 diff --git a/claasp/cipher_modules/models/sat/sat_models/sat_xor_differential_model.py b/claasp/cipher_modules/models/sat/sat_models/sat_xor_differential_model.py index b6155ffe..cf43a1b1 100644 --- a/claasp/cipher_modules/models/sat/sat_models/sat_xor_differential_model.py +++ b/claasp/cipher_modules/models/sat/sat_models/sat_xor_differential_model.py @@ -431,6 +431,7 @@ def find_one_xor_differential_trail_with_fixed_weight(self, fixed_weight, fixed_ sage: sat = SatXorDifferentialModel(speck) sage: sat.set_window_size_heuristic_by_round([0, 0, 0]) sage: trail = sat.find_one_xor_differential_trail_with_fixed_weight(3) + ... sage: trail['total_weight'] 3.0 diff --git a/claasp/cipher_modules/models/sat/utils/n_window_heuristic_helper.py b/claasp/cipher_modules/models/sat/utils/n_window_heuristic_helper.py index 61e6ff42..909d5d40 100644 --- a/claasp/cipher_modules/models/sat/utils/n_window_heuristic_helper.py +++ b/claasp/cipher_modules/models/sat/utils/n_window_heuristic_helper.py @@ -134,14 +134,15 @@ def generate_window_size_clauses(first_input_difference, second_input_difference - ``c`` -- **list**: List of binary variables representing the input differences c - ``aux`` -- **integer**: Auxiliary variable used to store the conjunctions of the carry differences from the addition of the first n - 1 bit differences of a and b - EXAMPLES: - :: + EXAMPLES:: + + sage: from claasp.cipher_modules.models.sat.utils.n_window_heuristic_helper import generate_window_size_clauses sage: a = [1, 2, 3, 4] sage: b = [5, 6, 7, 8] sage: c = [9, 10, 11, 12] sage: aux = 10 - sage: cnf = window_size_3_cnf(a, b, c, aux) - sage: cnf + sage: cnf = generate_window_size_clauses(a, b, c, aux) # doctest:+SKIP + sage: cnf # doctest:+SKIP ['4 -4 -10', '8 -10 -8'] """ window_size_plus_one = len(first_input_difference) diff --git a/claasp/cipher_modules/models/smt/smt_models/smt_xor_linear_model.py b/claasp/cipher_modules/models/smt/smt_models/smt_xor_linear_model.py index 1bfaf8a2..e252e0c6 100644 --- a/claasp/cipher_modules/models/smt/smt_models/smt_xor_linear_model.py +++ b/claasp/cipher_modules/models/smt/smt_models/smt_xor_linear_model.py @@ -249,8 +249,8 @@ def find_all_xor_linear_trails_with_weight_at_most(self, min_weight, max_weight, sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher sage: speck = SpeckBlockCipher(number_of_rounds=3) sage: smt = SmtXorLinearModel(speck) - sage: trails = smt.find_all_xor_linear_trails_with_weight_at_most(0, 2) # long - sage: len(trails) + sage: trails = smt.find_all_xor_linear_trails_with_weight_at_most(0, 2) # long # doctest: +SKIP + sage: len(trails) # doctest: +SKIP 187 # including the key schedule in the model @@ -303,7 +303,7 @@ def find_lowest_weight_xor_linear_trail(self, fixed_values=[], solver_name=solve sage: smt = SmtXorLinearModel(speck) sage: trail = smt.find_lowest_weight_xor_linear_trail() sage: trail['total_weight'] - 2.0 + 1.0 # including the key schedule in the model sage: from claasp.cipher_modules.models.smt.smt_models.smt_xor_linear_model import SmtXorLinearModel diff --git a/claasp/cipher_modules/models/utils.py b/claasp/cipher_modules/models/utils.py index 3c1dedfa..11695a01 100644 --- a/claasp/cipher_modules/models/utils.py +++ b/claasp/cipher_modules/models/utils.py @@ -64,7 +64,7 @@ def convert_solver_solution_to_dictionary(cipher, model_type, solver_name, solve sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher sage: speck = SpeckBlockCipher(number_of_rounds=4) sage: convert_solver_solution_to_dictionary(speck.id, 'xor_differential', 'z3', 0.239, 175.5, [], 0) - {'cipher_id': 'speck_p32_k64_o32_r4', + {'cipher': 'speck_p32_k64_o32_r4', 'components_values': [], 'memory_megabytes': 175.500000000000, 'model_type': 'xor_differential', diff --git a/claasp/cipher_modules/neural_network_tests.py b/claasp/cipher_modules/neural_network_tests.py index dbcf0528..730efceb 100644 --- a/claasp/cipher_modules/neural_network_tests.py +++ b/claasp/cipher_modules/neural_network_tests.py @@ -40,27 +40,31 @@ def neural_network_blackbox_distinguisher_tests(self, nb_samples=10000, sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher sage: from claasp.cipher_modules.neural_network_tests import NeuralNetworkTests - sage: NeuralNetworkTests(SpeckBlockCipher(number_of_rounds=2)).neural_network_blackbox_distinguisher_tests(nb_samples=10) - {'input_parameters': {'test_name': 'neural_network_blackbox_distinguisher_tests', - 'number_of_samples': 10, - 'hidden_layers': [32, 32, 32], - 'number_of_epochs': 10}, - 'test_results': {'plaintext': {'round_key_output': {'neural_network_blackbox_distinguisher': [{'accuracies': [1.0, - 0.0], - 'component_ids': ['intermediate_output_0_5', - 'intermediate_output_1_11']}]}, - 'round_output': {'neural_network_blackbox_distinguisher': [{'accuracies': [0.0], - 'component_ids': ['intermediate_output_0_6']}]}, - 'cipher_output': {'neural_network_blackbox_distinguisher': [{'accuracies': [1.0], - 'component_ids': ['cipher_output_1_12']}]}}, - 'key': {'round_key_output': {'neural_network_blackbox_distinguisher': [{'accuracies': [0.0, - 0.0], - 'component_ids': ['intermediate_output_0_5', - 'intermediate_output_1_11']}]}, - 'round_output': {'neural_network_blackbox_distinguisher': [{'accuracies': [0.0], - 'component_ids': ['intermediate_output_0_6']}]}, - 'cipher_output': {'neural_network_blackbox_distinguisher': [{'accuracies': [1.0], - 'component_ids': ['cipher_output_1_12']}]}}}} + ... + sage: NeuralNetworkTests(SpeckBlockCipher(number_of_rounds=2)).neural_network_blackbox_distinguisher_tests(nb_samples=10) # random + ... + {'input_parameters': {'cipher': speck_p32_k64_o32_r2, + 'hidden_layers': [32, 32, 32], + 'number_of_epochs': 10, + 'number_of_samples': 10, + 'test_name': 'neural_network_blackbox_distinguisher_tests'}, + 'test_results': {'key': {'cipher_output': {'neural_network_blackbox_distinguisher': [{'accuracies': [0.0], + 'component_ids': ['cipher_output_1_12']}]}, + 'round_key_output': {'neural_network_blackbox_distinguisher': [{'accuracies': [1.0, + 0.0], + 'component_ids': ['intermediate_output_0_5', + 'intermediate_output_1_11']}]}, + 'round_output': {'neural_network_blackbox_distinguisher': [{'accuracies': [1.0], + 'component_ids': ['intermediate_output_0_6']}]}}, + 'plaintext': {'cipher_output': {'neural_network_blackbox_distinguisher': [{'accuracies': [1.0], + 'component_ids': ['cipher_output_1_12']}]}, + 'round_key_output': {'neural_network_blackbox_distinguisher': [{'accuracies': [1.0, + 1.0], + 'component_ids': ['intermediate_output_0_5', + 'intermediate_output_1_11']}]}, + 'round_output': {'neural_network_blackbox_distinguisher': [{'accuracies': [1.0], + 'component_ids': ['intermediate_output_0_6']}]}}}} + """ results = {"input_parameters": { "test_name": "neural_network_blackbox_distinguisher_tests", @@ -221,37 +225,39 @@ def neural_network_differential_distinguisher_tests(self, nb_samples=10000, hidd sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher sage: from claasp.cipher_modules.neural_network_tests import NeuralNetworkTests - sage: NeuralNetworkTests(SpeckBlockCipher(number_of_rounds=2)).neural_network_differential_distinguisher_tests(nb_samples=10) - {'input_parameters': {'test_name': 'neural_network_differential_distinguisher_tests', - 'number_of_samples': 10, - 'input_differences': [[4194304], [10]], - 'hidden_layers': [32, 32, 32], - 'min_accuracy_value': 0, - 'max_accuracy_value': 1, - 'output_bit_size': 32, - 'number_of_epochs': 10, - 'plaintext_input_bit_size': 32, - 'key_input_bit_size': 64}, - 'test_results': {'plaintext': {'round_key_output': {'neural_network_differential_distinguisher': [{'accuracies': [1.0, - 1.0], - 'component_ids': ['intermediate_output_0_5', 'intermediate_output_1_11'], - 'input_difference_value': '0x400000'}]}, - 'round_output': {'neural_network_differential_distinguisher': [{'accuracies': [0.0], - 'component_ids': ['intermediate_output_0_6'], - 'input_difference_value': '0x400000'}]}, - 'cipher_output': {'neural_network_differential_distinguisher': [{'accuracies': [0.0], - 'component_ids': ['cipher_output_1_12'], - 'input_difference_value': '0x400000'}]}}, - 'key': {'round_key_output': {'neural_network_differential_distinguisher': [{'accuracies': [1.0, - 1.0], - 'component_ids': ['intermediate_output_0_5', 'intermediate_output_1_11'], - 'input_difference_value': '0xa'}]}, - 'round_output': {'neural_network_differential_distinguisher': [{'accuracies': [1.0], - 'component_ids': ['intermediate_output_0_6'], - 'input_difference_value': '0xa'}]}, - 'cipher_output': {'neural_network_differential_distinguisher': [{'accuracies': [1.0], - 'component_ids': ['cipher_output_1_12'], - 'input_difference_value': '0xa'}]}}}} + sage: NeuralNetworkTests(SpeckBlockCipher(number_of_rounds=2)).neural_network_differential_distinguisher_tests(nb_samples=10) # random + ... + {'input_parameters': {'test_name': 'neural_network_differential_distinguisher_tests', + 'cipher': speck_p32_k64_o32_r2, + 'number_of_samples': 10, + 'input_differences': [[4194304], [10]], + 'hidden_layers': [32, 32, 32], + 'min_accuracy_value': 0, + 'max_accuracy_value': 1, + 'output_bit_size': 32, + 'number_of_epochs': 10, + 'plaintext_input_bit_size': 32, + 'key_input_bit_size': 64}, + 'test_results': {'plaintext': {'cipher_output': {'neural_network_differential_distinguisher': [{'accuracies': [1.0], + 'component_ids': ['cipher_output_1_12'], + 'input_difference_value': '0x400000'}]}, + 'round_output': {'neural_network_differential_distinguisher': [{'accuracies': [1.0], + 'component_ids': ['intermediate_output_0_6'], + 'input_difference_value': '0x400000'}]}, + 'round_key_output': {'neural_network_differential_distinguisher': [{'accuracies': [0.0, + 1.0], + 'component_ids': ['intermediate_output_0_5', 'intermediate_output_1_11'], + 'input_difference_value': '0x400000'}]}}, + 'key': {'cipher_output': {'neural_network_differential_distinguisher': [{'accuracies': [0.0], + 'component_ids': ['cipher_output_1_12'], + 'input_difference_value': '0xa'}]}, + 'round_output': {'neural_network_differential_distinguisher': [{'accuracies': [0.0], + 'component_ids': ['intermediate_output_0_6'], + 'input_difference_value': '0xa'}]}, + 'round_key_output': {'neural_network_differential_distinguisher': [{'accuracies': [1.0, + 1.0], + 'component_ids': ['intermediate_output_0_5', 'intermediate_output_1_11'], + 'input_difference_value': '0xa'}]}}}} """ results = {"input_parameters": { @@ -424,62 +430,64 @@ def train_neural_distinguisher(self, data_generator, starting_round, neural_netw EXAMPLES:: - sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher - sage: from claasp.cipher_modules.neural_network_tests import NeuralNetworkTests - sage: speck = SpeckBlockCipher() - sage: tester = NeuralNetworkTests(speck) - sage: input_differences = [0x400000, 0] - sage: data_generator = lambda nr, samples: tester.get_differential_dataset(input_differences, number_of_rounds = nr, samples = samples) - sage: neural_network = tester.get_neural_network('gohr_resnet', input_size = 64) - sage: tester.train_neural_distinguisher(data_generator, starting_round = 5, neural_network = neural_network, - training_samples = 1000, testing_samples=1000) - Epoch 1/5 - 1/1 [==============================] - 2s 2s/step - loss: 0.3249 - acc: 0.4930 - val_loss: 0.2640 - val_acc: 0.4950 - Epoch 2/5 - 1/1 [==============================] - 0s 102ms/step - loss: 0.2797 - acc: 0.5570 - val_loss: 0.2624 - val_acc: 0.4950 - Epoch 3/5 - 1/1 [==============================] - 0s 102ms/step - loss: 0.2435 - acc: 0.6080 - val_loss: 0.2609 - val_acc: 0.4950 - Epoch 4/5 - 1/1 [==============================] - 0s 105ms/step - loss: 0.2142 - acc: 0.6640 - val_loss: 0.2595 - val_acc: 0.4930 - Epoch 5/5 - 1/1 [==============================] - 0s 102ms/step - loss: 0.1896 - acc: 0.7090 - val_loss: 0.2583 - val_acc: 0.4930 - Validation accuracy at 5 rounds :0.4950000047683716 - {5: 0.4950000047683716} - sage: sage: tester.train_neural_distinguisher(data_generator, starting_round = 5, neural_network = neural_network, training_samples = 10**5, testing_samples=10**4) - Epoch 1/5 - 20/20 [==============================] - 7s 337ms/step - loss: 0.1979 - acc: 0.7259 - val_loss: 0.2284 - val_acc: 0.7019 - Epoch 2/5 - 20/20 [==============================] - 7s 338ms/step - loss: 0.1586 - acc: 0.7936 - val_loss: 0.2274 - val_acc: 0.7083 - Epoch 3/5 - 20/20 [==============================] - 7s 361ms/step - loss: 0.1260 - acc: 0.8389 - val_loss: 0.2298 - val_acc: 0.5813 - Epoch 4/5 - 20/20 [==============================] - 7s 349ms/step - loss: 0.1089 - acc: 0.8560 - val_loss: 0.2334 - val_acc: 0.5309 - Epoch 5/5 - 20/20 [==============================] - 7s 364ms/step - loss: 0.1040 - acc: 0.8633 - val_loss: 0.2320 - val_acc: 0.5244 - Validation accuracy at 5 rounds :0.708299994468689 - Epoch 1/5 - 20/20 [==============================] - 7s 363ms/step - loss: 0.2627 - acc: 0.6160 - val_loss: 0.2529 - val_acc: 0.5367 - Epoch 2/5 - 20/20 [==============================] - 7s 362ms/step - loss: 0.2214 - acc: 0.6630 - val_loss: 0.2410 - val_acc: 0.6018 - Epoch 3/5 - 20/20 [==============================] - 7s 360ms/step - loss: 0.2123 - acc: 0.6765 - val_loss: 0.2378 - val_acc: 0.6105 - Epoch 4/5 - 20/20 [==============================] - 7s 331ms/step - loss: 0.2079 - acc: 0.6857 - val_loss: 0.2351 - val_acc: 0.6217 - Epoch 5/5 - 20/20 [==============================] - 7s 331ms/step - loss: 0.2050 - acc: 0.6894 - val_loss: 0.2334 - val_acc: 0.6277 - Validation accuracy at 6 rounds :0.6276999711990356 + sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher + sage: from claasp.cipher_modules.neural_network_tests import NeuralNetworkTests + sage: speck = SpeckBlockCipher() + sage: tester = NeuralNetworkTests(speck) + sage: input_differences = [0x400000, 0] + sage: data_generator = lambda nr, samples: tester.get_differential_dataset(input_differences, number_of_rounds = nr, samples = samples) + sage: neural_network = tester.get_neural_network('gohr_resnet', input_size = 64) + ... + sage: tester.train_neural_distinguisher(data_generator, starting_round = 5, neural_network = neural_network, training_samples = 1000, testing_samples=1000) # random Epoch 1/5 - 20/20 [==============================] - 7s 337ms/step - loss: 0.2678 - acc: 0.4966 - val_loss: 0.2616 - val_acc: 0.4959 - Epoch 2/5 - 20/20 [==============================] - 7s 335ms/step - loss: 0.2537 - acc: 0.5215 - val_loss: 0.2614 - val_acc: 0.4962 - Epoch 3/5 - 20/20 [==============================] - 7s 342ms/step - loss: 0.2505 - acc: 0.5366 - val_loss: 0.2588 - val_acc: 0.4978 - Epoch 4/5 - 20/20 [==============================] - 7s 357ms/step - loss: 0.2487 - acc: 0.5496 - val_loss: 0.2567 - val_acc: 0.4963 - Epoch 5/5 - 20/20 [==============================] - 7s 354ms/step - loss: 0.2473 - acc: 0.5592 - val_loss: 0.2562 - val_acc: 0.4981 - Validation accuracy at 7 rounds :0.49810001254081726 - {5: 0.708299994468689, 6: 0.6276999711990356, 7: 0.49810001254081726} + 1/1 [==============================] - 4s 4s/step - loss: 0.2834 - acc: 0.5010 - val_loss: 0.2524 - val_acc: 0.5110 + Epoch 2/5 + 1/1 [==============================] - 0s 176ms/step - loss: 0.2291 - acc: 0.6300 - val_loss: 0.2518 - val_acc: 0.5180 + Epoch 3/5 + 1/1 [==============================] - 0s 139ms/step - loss: 0.1872 - acc: 0.7500 - val_loss: 0.2512 - val_acc: 0.5270 + Epoch 4/5 + 1/1 [==============================] - 0s 142ms/step - loss: 0.1558 - acc: 0.8230 - val_loss: 0.2507 - val_acc: 0.5410 + Epoch 5/5 + 1/1 [==============================] - 0s 136ms/step - loss: 0.1320 - acc: 0.8790 - val_loss: 0.2502 - val_acc: 0.5530 + Validation accuracy at 5 rounds :0.5529999732971191 + {5: 0.5529999732971191} + + sage: tester.train_neural_distinguisher(data_generator, starting_round = 5, neural_network = neural_network, training_samples = 10**5, testing_samples=10**4) # random + Epoch 1/5 + 20/20 [==============================] - 3s 154ms/step - loss: 0.1911 - acc: 0.7253 - val_loss: 0.2402 - val_acc: 0.7036 + Epoch 2/5 + 20/20 [==============================] - 3s 172ms/step - loss: 0.1573 - acc: 0.7893 - val_loss: 0.2400 - val_acc: 0.6793 + Epoch 3/5 + 20/20 [==============================] - 3s 155ms/step - loss: 0.1312 - acc: 0.8268 - val_loss: 0.2398 - val_acc: 0.5701 + Epoch 4/5 + 20/20 [==============================] - 3s 127ms/step - loss: 0.1128 - acc: 0.8528 - val_loss: 0.2463 - val_acc: 0.5010 + Epoch 5/5 + 20/20 [==============================] - 2s 124ms/step - loss: 0.1061 - acc: 0.8620 - val_loss: 0.2522 - val_acc: 0.4992 + Validation accuracy at 5 rounds :0.7035999894142151 + Epoch 1/5 + 20/20 [==============================] - 3s 131ms/step - loss: 0.2619 - acc: 0.6157 - val_loss: 0.2505 - val_acc: 0.5325 + Epoch 2/5 + 20/20 [==============================] - 2s 122ms/step - loss: 0.2218 - acc: 0.6634 - val_loss: 0.2442 - val_acc: 0.5950 + Epoch 3/5 + 20/20 [==============================] - 3s 127ms/step - loss: 0.2121 - acc: 0.6788 - val_loss: 0.2419 - val_acc: 0.6051 + Epoch 4/5 + 20/20 [==============================] - 3s 126ms/step - loss: 0.2073 - acc: 0.6881 - val_loss: 0.2396 - val_acc: 0.6086 + Epoch 5/5 + 20/20 [==============================] - 2s 125ms/step - loss: 0.2043 - acc: 0.6933 - val_loss: 0.2372 - val_acc: 0.6131 + Validation accuracy at 6 rounds :0.613099992275238 + Epoch 1/5 + 20/20 [==============================] - 3s 164ms/step - loss: 0.2673 - acc: 0.4976 - val_loss: 0.2670 - val_acc: 0.4949 + Epoch 2/5 + 20/20 [==============================] - 3s 125ms/step - loss: 0.2535 - acc: 0.5268 - val_loss: 0.2634 - val_acc: 0.4946 + Epoch 3/5 + 20/20 [==============================] - 2s 117ms/step - loss: 0.2499 - acc: 0.5426 - val_loss: 0.2598 - val_acc: 0.4933 + Epoch 4/5 + 20/20 [==============================] - 2s 125ms/step - loss: 0.2478 - acc: 0.5578 - val_loss: 0.2584 - val_acc: 0.4939 + Epoch 5/5 + 20/20 [==============================] - 2s 112ms/step - loss: 0.2460 - acc: 0.5692 - val_loss: 0.2575 - val_acc: 0.4958 + Validation accuracy at 7 rounds :0.4957999885082245 + {5: 0.7035999894142151, 6: 0.613099992275238, 7: 0.4957999885082245} + """ acc = {} bs = 5000 @@ -525,11 +533,11 @@ def train_gohr_neural_distinguisher(self, input_difference, number_of_rounds, de sage: tester = NeuralNetworkTests(speck) sage: input_differences = [0x400000, 0] sage: number_of_rounds = 5 - sage: tester.train_gohr_neural_distinguisher(input_differences, number_of_rounds, training_samples = 10**5, testing_samples = 10**4, number_of_epochs = 1) - Word size not specified for gohr_resnet , defaulting to ciphertext size... - 20/20 [==============================] - 8s 335ms/step - loss: 0.2041 - acc: 0.6909 - val_loss: 0.2476 - val_acc: 0.5528 - Validation accuracy at 5 rounds :0.5527999997138977 - {5: 0.5527999997138977} + sage: tester.train_gohr_neural_distinguisher(input_differences, number_of_rounds, training_samples = 10**5, testing_samples = 10**4, number_of_epochs = 1) # random + Word size not specified for gohr_resnet , defaulting to ciphertext size... + 20/20 [==============================] - 8s 335ms/step - loss: 0.2041 - acc: 0.6909 - val_loss: 0.2476 - val_acc: 0.5528 + Validation accuracy at 5 rounds :0.5527999997138977 + {5: 0.5527999997138977} """ def data_generator(nr, samples): @@ -567,34 +575,82 @@ def run_autond_pipeline(self, difference_positions=None, optimizer_samples=10 ** EXAMPLES:: - sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher - sage: from claasp.cipher_modules.neural_network_tests import NeuralNetworkTests - sage: speck = SpeckBlockCipher() - sage: tester = NeuralNetworkTests(speck) - sage: tester.run_autond_pipeline(difference_positions=[True, False], optimizer_samples=10 ** 3, optimizer_generations=5, - training_samples=10 ** 5, testing_samples=10 ** 5, number_of_epochs=1, verbose=True, - neural_net = 'dbitnet', save_prefix=None) - Generation 0/5, 1625 nodes explored, 32 current, best is ['0x305ed470', '0x305e5470', '0x3e020058', '0x80fbf20'] with [0.42265625 0.468875 0.47771875 0.5191875 ] - Generation 1/5, 2169 nodes explored, 32 current, best is ['0x100', '0x20000000', '0x2000000', '0x8000'] with [1.69571875 2.09790625 2.1274375 2.4663125 ] - Generation 2/5, 2728 nodes explored, 32 current, best is ['0x40000000', '0x20000000', '0x2000000', '0x8000'] with [2.01571875 2.09790625 2.1274375 2.4663125 ] - Generation 3/5, 3137 nodes explored, 32 current, best is ['0x2000000', '0x40000', '0x2000004', '0x8000'] with [2.1274375 2.12903125 2.22596875 2.4663125 ] - Generation 4/5, 3383 nodes explored, 32 current, best is ['0x40000', '0x2000004', '0x8000', '0x200000'] with [2.12903125 2.22596875 2.4663125 2.54446875] - The highest reached round was 5 - The best differences found by the optimizer are... - 0x200000 , with score 2.54446875 - 0x8000 , with score 2.4663125000000004 - 0x2000004 , with score 2.22596875 - 0x40000 , with score 2.12903125 - 0x2000000 , with score 2.1274375 - 0x4000000 , with score 2.09978125 - 0x20000000 , with score 2.0979062500000003 - 0x10000 , with score 2.03634375 - 0x40000000 , with score 2.0157187499999996 - 0x40200000 , with score 1.75265625 - Training dbitnet on input difference ['0x200000', '0x0'] (['plaintext', 'key']), from round 2... - 20/20 [==============================] - 31s 1s/step - loss: 0.0884 - acc: 0.8838 - val_loss: 0.2889 - val_acc: 0.4993 - Validation accuracy at 2 rounds :0.49932000041007996 - {2: 0.49932000041007996} + + sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher + sage: from claasp.cipher_modules.neural_network_tests import NeuralNetworkTests + sage: speck = SpeckBlockCipher() + sage: tester = NeuralNetworkTests(speck) + sage: tester.run_autond_pipeline(difference_positions=[True, False], optimizer_samples=10 ** 3, optimizer_generations=5,\ + training_samples=10 ** 5, testing_samples=10 ** 5, number_of_epochs=1, verbose=True, neural_net = 'dbitnet', save_prefix=None) # random + + Generation 0/5, 1614 nodes explored, 32 current, best is ['0x700090b', '0x3e08030', '0x3033f440', '0x7f9aa3fe'] with [0.4184375 0.41859375 0.41959375 0.436 ] + Generation 1/5, 2158 nodes explored, 32 current, best is ['0x100', '0x40', '0x4', '0x8'] with [1.66334375 1.72559375 1.72803125 1.75125 ] + Generation 2/5, 2711 nodes explored, 32 current, best is ['0x8', '0x20000', '0x4000000', '0x100000'] with [1.75125 2.09603125 2.1125625 2.1784375 ] + Generation 3/5, 3129 nodes explored, 32 current, best is ['0x20000', '0x4000000', '0x100000', '0x4000008'] with [2.09603125 2.1125625 2.1784375 2.1988125 ] + Generation 4/5, 3377 nodes explored, 32 current, best is ['0x20000', '0x4000000', '0x100000', '0x4000008'] with [2.09603125 2.1125625 2.1784375 2.1988125 ] + The highest reached round was 5 + The best differences found by the optimizer are... + 0x4000008 , with score 2.1988125 + 0x100000 , with score 2.1784375000000002 + 0x4000000 , with score 2.1125625 + 0x20000 , with score 2.0960312500000002 + 0x1000000 , with score 2.00075 + 0x10 , with score 1.79246875 + 0x200 , with score 1.77490625 + 0x8 , with score 1.7512500000000004 + 0x4 , with score 1.7280312500000001 + 0x40 , with score 1.7255937500000003 + Training dbitnet on input difference ['0x4000008', '0x0'] (['plaintext', 'key']), from round 2... + 20/20 [==============================] - 24s 846ms/step - loss: 0.1065 - acc: 0.8606 - val_loss: 0.2000 - val_acc: 0.7100 + Validation accuracy at 2 rounds :0.7100499868392944 + 20/20 [==============================] - 15s 748ms/step - loss: 0.1077 - acc: 0.8740 - val_loss: 0.3309 - val_acc: 0.5004 + Validation accuracy at 3 rounds :0.5003799796104431 + {'input_parameters': {'test_name': 'neural_distinguisher_test', + 'cipher': speck_p32_k64_o32_r22, + 'optimizer_samples': 1000, + 'optimizer_generations': 5, + 'training_samples': 100000, + 'testing_samples': 100000, + 'number_of_epochs': 1, + 'neural_net': 'dbitnet'}, + 'test_results': {'plaintext': {'cipher_output': {'neural_distinguisher_test': [{'accuracies': [0.7100499868392944, + 0.5003799796104431], + 'plaintext_diff': '0x4000008', + 'key_diff': '0x0'}], + 'differences_scores': {'0x400000c': 1.30846875, + '0x100040': 1.31015625, + '0x4100000': 1.3121875, + '0x20004': 1.3249375, + '0x4020008': 1.33246875, + '0x20100': 1.3404687500000003, + '0xc': 1.3459062500000003, + '0x300': 1.35553125, + '0x18': 1.3560625000000002, + '0x4010200': 1.38396875, + '0x4000010': 1.3880000000000003, + '0x40004': 1.3904062500000003, + '0x600000c': 1.41065625, + '0x4100008': 1.41415625, + '0x1020000': 1.43640625, + '0x100010': 1.45040625, + '0x4020000': 1.4833124999999998, + '0x4000018': 1.5420625000000001, + '0x4000004': 1.5525625000000003, + '0x20200': 1.55865625, + '0x100': 1.66334375, + '0x6000000': 1.6745937499999999, + '0x40': 1.7255937500000003, + '0x4': 1.7280312500000001, + '0x8': 1.7512500000000004, + '0x200': 1.77490625, + '0x10': 1.79246875, + '0x1000000': 2.00075, + '0x20000': 2.0960312500000002, + '0x4000000': 2.1125625, + '0x100000': 2.1784375000000002, + '0x4000008': 2.1988125}}}, + 'round_start': 2}} + """ neural_distinguisher_test_results = { @@ -781,7 +837,25 @@ def find_good_input_difference_for_neural_distinguisher(self, difference_positio sage: from claasp.cipher_modules.neural_network_tests import NeuralNetworkTests sage: speck = SpeckBlockCipher() sage: tester = NeuralNetworkTests(speck) - sage: diff, scores, highest_round = tester.find_good_input_difference_for_neural_distinguisher([True, False], verbose = True, number_of_generations=5) + sage: diff, scores, highest_round = tester.find_good_input_difference_for_neural_distinguisher([True, False], verbose = True, number_of_generations=5) # random + Generation 0/5, 1623 nodes explored, 32 current, best is ['0x88580b10', '0x88582a10', '0xa1ffc14', '0xbf8184fe'] with [0.4386875 0.44759375 0.46746875 0.5376875 ] + Generation 1/5, 2164 nodes explored, 32 current, best is ['0x42840a85', '0x14220830', '0xbf8184fe', '0x2100'] with [0.4893125 0.50771875 0.5376875 0.85790625] + Generation 2/5, 2647 nodes explored, 32 current, best is ['0x20a018', '0x2100', '0x40', '0x2000000'] with [0.79275 0.85790625 1.7469375 2.04596875] + Generation 3/5, 3185 nodes explored, 32 current, best is ['0x2', '0x40', '0x2000000', '0x4000'] with [1.7279375 1.7469375 2.04596875 2.07025 ] + Generation 4/5, 3671 nodes explored, 32 current, best is ['0x4000000', '0x80000', '0x81000', '0x400000'] with [2.19903125 2.20821875 2.45065625 3.45453125] + The highest reached round was 6 + The best differences found by the optimizer are... + 0x400000 , with score 3.45453125 + 0x81000 , with score 2.4506562499999998 + 0x80000 , with score 2.2082187500000003 + 0x4000000 , with score 2.19903125 + 0x4000 , with score 2.07025 + 0x2000000 , with score 2.04596875 + 0x8 , with score 1.8199375000000002 + 0x6000000 , with score 1.7656562500000001 + 0x40 , with score 1.7469375 + 0x2 , with score 1.7279375000000001 + """ # Initialisation diff --git a/claasp/cipher_modules/report.py b/claasp/cipher_modules/report.py index c2fa5b9d..97916d52 100644 --- a/claasp/cipher_modules/report.py +++ b/claasp/cipher_modules/report.py @@ -132,7 +132,7 @@ def __init__(self, test_report): ....: bit_positions=range(64), ....: bit_values=(0,)*64) sage: trail = sat.find_lowest_weight_xor_differential_trail(fixed_values=[plaintext, key]) - sage: report = Report(speck, trail) + sage: report = Report(trail) """ @@ -857,11 +857,12 @@ def save_as_image(self, show_as_hex=False, test_name=None, fixed_input=None, fix EXAMPLES: sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher + sage: from claasp.cipher_modules.avalanche_tests import AvalancheTests sage: from claasp.cipher_modules.report import Report sage: speck = SpeckBlockCipher(number_of_rounds=5) - sage: avalanche_test_results = speck.diffusion_tests() - sage: report = Report(speck, avalanche_test_results) - sage: report.save_as_image() + sage: avalanche_test_results = AvalancheTests(speck).avalanche_tests() + sage: report = Report(avalanche_test_results) + sage: report.save_as_image(test_name='avalanche_weight_vectors', fixed_input='plaintext', fixed_output='round_output', fixed_input_difference='average') # random """ time = '_date:' + 'time:'.join(str(datetime.now()).split(' ')) diff --git a/claasp/cipher_modules/statistical_tests/nist_statistical_tests.py b/claasp/cipher_modules/statistical_tests/nist_statistical_tests.py index 1b2abceb..85e7e4a0 100644 --- a/claasp/cipher_modules/statistical_tests/nist_statistical_tests.py +++ b/claasp/cipher_modules/statistical_tests/nist_statistical_tests.py @@ -280,10 +280,10 @@ def _run_nist_statistical_tests_tool(input_file, bit_stream_length=10000, number EXAMPLES:: sage: import os - sage: from claasp.cipher_modules.statistical_tests.nist_statistical_tests import StatisticalTests + sage: from claasp.cipher_modules.statistical_tests.nist_statistical_tests import NISTStatisticalTests sage: if not os.path.exists(f'test_reports/statistical_tests/experiments'): ....: os.makedirs(f'test_reports/statistical_tests/experiments') - sage: result = StatisticalTests._run_nist_statistical_tests_tool( + sage: result = NISTStatisticalTests._run_nist_statistical_tests_tool( ....: f'claasp/cipher_modules/statistical_tests/input_data_example', ....: 10000, 10, 1) Statistical Testing In Progress......... @@ -347,8 +347,8 @@ def _parse_report(report_filename, statistical_test_option_list='1' + 14 * '0'): EXAMPLES:: - sage: from claasp.cipher_modules.statistical_tests.nist_statistical_tests import StatisticalTests - sage: dict = StatisticalTests._parse_report(f'claasp/cipher_modules/statistical_tests/finalAnalysisReportExample.txt') + sage: from claasp.cipher_modules.statistical_tests.nist_statistical_tests import NISTStatisticalTests + sage: dict = NISTStatisticalTests._parse_report(f'claasp/cipher_modules/statistical_tests/finalAnalysisReportExample.txt') Parsing claasp/cipher_modules/statistical_tests/finalAnalysisReportExample.txt is in progress. Parsing claasp/cipher_modules/statistical_tests/finalAnalysisReportExample.txt is finished. """ diff --git a/claasp/ciphers/block_ciphers/lblock_block_cipher.py b/claasp/ciphers/block_ciphers/lblock_block_cipher.py index 66c82b37..6f646e83 100644 --- a/claasp/ciphers/block_ciphers/lblock_block_cipher.py +++ b/claasp/ciphers/block_ciphers/lblock_block_cipher.py @@ -44,9 +44,9 @@ class LBlockBlockCipher(Cipher): EXAMPLES:: sage: from claasp.ciphers.block_ciphers.lblock_block_cipher import LBlockBlockCipher - sage: lblock = LBlockBlockCipher(number_of_rounds=3) + sage: lblock = LBlockBlockCipher(number_of_rounds=32) sage: lblock.evaluate([0,0]) - 641582411206367315 + 13985955387709807565 """ def __init__(self, number_of_rounds=32): diff --git a/claasp/ciphers/block_ciphers/rc5_block_cipher.py b/claasp/ciphers/block_ciphers/rc5_block_cipher.py index a4be0f2c..7cafb6cd 100644 --- a/claasp/ciphers/block_ciphers/rc5_block_cipher.py +++ b/claasp/ciphers/block_ciphers/rc5_block_cipher.py @@ -40,7 +40,7 @@ class RC5BlockCipher(Cipher): sage: from claasp.ciphers.block_ciphers.rc5_block_cipher import RC5BlockCipher sage: rc5 = RC5BlockCipher() - sage: key = 0x0x0001020304050607 + sage: key = 0x0001020304050607 sage: plaintext = 0x00010203 sage: ciphertext = 0x23a8d72e sage: rc5.evaluate([key, plaintext]) == ciphertext diff --git a/claasp/ciphers/permutations/gaston_permutation.py b/claasp/ciphers/permutations/gaston_permutation.py index 2667526d..9df9aaf7 100644 --- a/claasp/ciphers/permutations/gaston_permutation.py +++ b/claasp/ciphers/permutations/gaston_permutation.py @@ -76,7 +76,7 @@ class GastonPermutation(Cipher): sage: gaston = GastonPermutation(number_of_rounds=12) sage: plaintext = 0x0 sage: ciphertext = 0x88B326096BEBC6356CA8FB64BC5CE6CAF1CE3840D819071354D70067438689B5F17FE863F958F32B - sage: print(gaston.evaluate([plaintext]))==ciphertext) + sage: print(gaston.evaluate([plaintext])==ciphertext) True sage: plaintext=0x1F4AD9906DA6A2544B84D7F83F2BDDFA468A0853578A00E36C05A0506DF7F66E4EFB22112453C964 diff --git a/claasp/component.py b/claasp/component.py index 301ac360..62e62072 100644 --- a/claasp/component.py +++ b/claasp/component.py @@ -181,7 +181,7 @@ def _get_independent_input_output_variables(self): sage: component = fancy.get_component_from_id("and_0_8") sage: l = component._get_independent_input_output_variables() sage: l[0] - ['and_0_8_0_i', + ['and_0_8_0_i', 'and_0_8_1_i', ... 'and_0_8_22_i', @@ -312,7 +312,7 @@ def _get_wordwise_input_output_linked_class(self, model): sage: from claasp.ciphers.block_ciphers.aes_block_cipher import AESBlockCipher sage: cipher = AESBlockCipher(number_of_rounds=3) - sage: from claasp.cipher_modules.models.milp.milp_models.milp_wordwise_deterministic_truncated_xor_differential_model import MilpWordwisewiseDeterministicTruncatedXorDifferentialModel + sage: from claasp.cipher_modules.models.milp.milp_models.milp_wordwise_deterministic_truncated_xor_differential_model import MilpWordwiseDeterministicTruncatedXorDifferentialModel sage: milp = MilpWordwiseDeterministicTruncatedXorDifferentialModel(cipher) sage: milp.init_model_in_sage_milp_class() sage: component = cipher.get_component_from_id("rot_0_18") diff --git a/claasp/components/linear_layer_component.py b/claasp/components/linear_layer_component.py index 9ce6e4f0..b3d5cee7 100644 --- a/claasp/components/linear_layer_component.py +++ b/claasp/components/linear_layer_component.py @@ -594,12 +594,12 @@ def milp_wordwise_deterministic_truncated_xor_differential_constraints(self, mod EXAMPLES:: sage: from claasp.ciphers.block_ciphers.midori_block_cipher import MidoriBlockCipher - sage: cipher = MidoriBlockCipher(number_of_rounds=2) sage: from claasp.cipher_modules.models.milp.milp_models.milp_wordwise_deterministic_truncated_xor_differential_model import MilpWordwiseDeterministicTruncatedXorDifferentialModel + sage: cipher = MidoriBlockCipher(number_of_rounds=2) sage: milp = MilpWordwiseDeterministicTruncatedXorDifferentialModel(cipher) sage: milp.init_model_in_sage_milp_class() sage: linear_layer_component = cipher.component_from(0, 21) - sage: variables, constraints = linear_layer_component.milp_wordwise_deterministic_truncated_xor_differential_constraints(milp) + sage: variables, constraints = linear_layer_component.milp_wordwise_deterministic_truncated_xor_differential_constraints(milp) # random sage: variables [('x[mix_column_0_20_word_0_class_bit_0]', x_0), ('x[mix_column_0_20_word_0_class_bit_1]', x_1), @@ -610,8 +610,8 @@ def milp_wordwise_deterministic_truncated_xor_differential_constraints(self, mod [1 <= 1 + x_6 + x_8 + x_9 + x_10 + x_11 + x_13 + x_18 + x_19 - x_25, 1 <= 1 + x_6 + x_8 + x_9 + x_10 + x_11 + x_12 + x_13 + x_19 - x_25, ... - 1 <= 2 - x_6 - x_8, - 1 <= 1 + x_7 - x_8] + 1 <= 1 + x_7 - x_8, + 1 <= 1 + x_1 - x_2] """ x = model.binary_variable diff --git a/claasp/components/mix_column_component.py b/claasp/components/mix_column_component.py index 28613fde..cc6a9a4d 100644 --- a/claasp/components/mix_column_component.py +++ b/claasp/components/mix_column_component.py @@ -648,7 +648,7 @@ def milp_wordwise_deterministic_truncated_xor_differential_constraints(self, mod sage: milp = MilpWordwiseDeterministicTruncatedXorDifferentialModel(aes) sage: milp.init_model_in_sage_milp_class() sage: mix_column_component = aes.component_from(0, 21) - sage: variables, constraints = mix_column_component.milp_wordwise_deterministic_truncated_xor_differential_constraints(milp) + sage: variables, constraints = mix_column_component.milp_wordwise_deterministic_truncated_xor_differential_constraints(milp) # random sage: variables [('x[rot_0_17_word_0_class_bit_0]', x_0), ('x[rot_0_17_word_0_class_bit_1]', x_1), @@ -656,8 +656,8 @@ def milp_wordwise_deterministic_truncated_xor_differential_constraints(self, mod ('x[mix_column_0_21_word_3_class_bit_0]', x_14), ('x[mix_column_0_21_word_3_class_bit_1]', x_15)] sage: constraints - [1 <= 1 + x_0 + x_1 + x_2 + x_3 + x_4 + x_5 - x_15, - 1 <= 1 + x_0 + x_1 + x_2 + x_3 + x_6 + x_7 - x_15, + [1 <= 1 + x_0 + x_1 + x_2 + x_3 + x_4 + x_5 + x_6 - x_15, + 1 <= 1 + x_0 + x_1 + x_2 + x_3 + x_4 + x_5 + x_7 - x_15, ... 1 <= 1 - x_11 + x_13, 1 <= 1 - x_9 + x_11] diff --git a/claasp/components/modadd_component.py b/claasp/components/modadd_component.py index dbb10ed0..612e4e6b 100644 --- a/claasp/components/modadd_component.py +++ b/claasp/components/modadd_component.py @@ -328,9 +328,9 @@ def sat_constraints(self): sage: speck = SpeckBlockCipher(number_of_rounds=3) sage: modadd_component = speck.component_from(0, 1) sage: modadd_component.sat_constraints() - (['carry_modadd_0_1_0', - 'carry_modadd_0_1_1', - 'carry_modadd_0_1_2', + (['carry_0_modadd_0_1_0', + 'carry_0_modadd_0_1_1', + 'carry_0_modadd_0_1_2', ... 'modadd_0_1_15 -rot_0_0_15 plaintext_31', 'modadd_0_1_15 rot_0_0_15 -plaintext_31', diff --git a/claasp/components/modular_component.py b/claasp/components/modular_component.py index 4fc751b7..e6e43e57 100644 --- a/claasp/components/modular_component.py +++ b/claasp/components/modular_component.py @@ -355,10 +355,10 @@ def milp_xor_differential_propagation_constraints(self, model): EXAMPLES:: sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher - sage: from claasp.cipher_modules.models.milp.milp_model import MilpModel + sage: from claasp.cipher_modules.models.milp.milp_models.milp_xor_differential_model import MilpXorDifferentialModel sage: speck = SpeckBlockCipher(block_bit_size=32, key_bit_size=64, number_of_rounds=2) sage: modadd_component = speck.component_from(0, 1) - sage: milp = MilpModel(speck) + sage: milp = MilpXorDifferentialModel(speck) sage: milp.init_model_in_sage_milp_class() sage: variables, constraints = modadd_component.milp_xor_differential_propagation_constraints(milp) sage: variables @@ -453,7 +453,7 @@ def milp_bitwise_deterministic_truncated_xor_differential_constraints(self, mode sage: modadd_component = cipher.get_component_from_id("modadd_0_1") sage: variables, constraints = modadd_component.milp_bitwise_deterministic_truncated_xor_differential_constraints(milp) sage: constraints - [x_48 <= 16, + [x_48 <= 15, 0 <= x_48, 0 <= 16 + x_48 - 17*x_49, x_48 - 17*x_49 <= 0, @@ -627,7 +627,7 @@ def minizinc_xor_differential_propagation_constraints(self, model): sage: modadd_component = fancy.component_from(1, 9) sage: _, constraints = modadd_component.minizinc_xor_differential_propagation_constraints(minizinc) sage: constraints[6] - 'constraint modular_addition_word(array1d(0..6-1, [modadd_1_9_x0,modadd_1_9_x1,modadd_1_9_x2,modadd_1_9_x3,modadd_1_9_x4,modadd_1_9_x5]),array1d(0..6-1, [modadd_1_9_x6,modadd_1_9_x7,modadd_1_9_x8,modadd_1_9_x9,modadd_1_9_x10,modadd_1_9_x11]),array1d(0..6-1, [modadd_1_9_y0_0,modadd_1_9_y1_0,modadd_1_9_y2_0,modadd_1_9_y3_0,modadd_1_9_y4_0,modadd_1_9_y5_0]), p_modadd_1_9_0, dummy_modadd_1_9_0, -1)=1;\n' + 'constraint modular_addition_word(array1d(0..6-1, [modadd_1_9_x0,modadd_1_9_x1,modadd_1_9_x2,modadd_1_9_x3,modadd_1_9_x4,modadd_1_9_x5]),array1d(0..6-1, [modadd_1_9_x6,modadd_1_9_x7,modadd_1_9_x8,modadd_1_9_x9,modadd_1_9_x10,modadd_1_9_x11]),array1d(0..6-1, [modadd_1_9_y0_0,modadd_1_9_y1_0,modadd_1_9_y2_0,modadd_1_9_y3_0,modadd_1_9_y4_0,modadd_1_9_y5_0]), p_modadd_1_9_0, dummy_modadd_1_9_0, -1)=1;\nconstraint carry_modadd_1_9_0 = XOR3(array1d(0..6-1, [modadd_1_9_x0,modadd_1_9_x1,modadd_1_9_x2,modadd_1_9_x3,modadd_1_9_x4,modadd_1_9_x5]),array1d(0..6-1, [modadd_1_9_x6,modadd_1_9_x7,modadd_1_9_x8,modadd_1_9_x9,modadd_1_9_x10,modadd_1_9_x11]),array1d(0..6-1, [modadd_1_9_y0_0,modadd_1_9_y1_0,modadd_1_9_y2_0,modadd_1_9_y3_0,modadd_1_9_y4_0,modadd_1_9_y5_0]));\n' """ def create_block_of_modadd_constraints(input_vars_1_temp, input_vars_2_temp, output_varstrs_temp, i, round_number): @@ -729,9 +729,9 @@ def milp_xor_linear_mask_propagation_constraints(self, model): EXAMPLES:: sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher - sage: from claasp.cipher_modules.models.milp.milp_model import MilpModel + sage: from claasp.cipher_modules.models.milp.milp_models.milp_xor_linear_model import MilpXorLinearModel sage: speck = SpeckBlockCipher(block_bit_size=32, key_bit_size=64, number_of_rounds=2) - sage: milp = MilpModel(speck) + sage: milp = MilpXorLinearModel(speck) sage: milp.init_model_in_sage_milp_class() sage: modadd_component = speck.component_from(0, 1) sage: variables, constraints = modadd_component.milp_xor_linear_mask_propagation_constraints(milp) @@ -746,7 +746,7 @@ def milp_xor_linear_mask_propagation_constraints(self, model): 0 <= -1*x_0 - x_16 + x_32 + x_48 + x_49, 0 <= x_0 + x_16 - x_32 + x_48 - x_49, ... - -4 <= x_15 + x_31 + x_47 + x_63 + x_64, + x_15 + x_31 + x_47 + x_63 + x_64 <= 4, x_65 == x_48 + x_49 + x_50 + x_51 + x_52 + x_53 + x_54 + x_55 + x_56 + x_57 + x_58 + x_59 + x_60 + x_61 + x_62 + x_63, x_66 == 100*x_65] """ @@ -877,11 +877,12 @@ def extend_constraints_for_window_size( hw_bit_ids[i: i + (model.window_size_weight_pr_vars + 1)])) component_round_number = model._cipher.get_round_from_component_id(self.id) - if model.window_size_by_round_values is not None: + from claasp.cipher_modules.models.sat.sat_models.sat_xor_differential_model import SatXorDifferentialModel + if type(model) == SatXorDifferentialModel and model.window_size_by_round_values is not None: window_size = model.window_size_by_round_values[component_round_number] extend_constraints_for_window_size(model, output_bit_len, window_size, input_bit_ids, output_bit_ids, constraints) - if model.window_size_by_component_id_values is not None: + if type(model) == SatXorDifferentialModel and model.window_size_by_component_id_values is not None: if self.id not in model.window_size_by_component_id_values: raise ValueError(f"component with id {self.id} is not in the list window_size_by_component_id") window_size = model.window_size_by_component_id_values[self.id] @@ -914,8 +915,8 @@ def sat_bitwise_deterministic_truncated_xor_differential_constraints(self): 'modadd_0_1_1_0', 'modadd_0_1_2_0', ... - 'rot_0_0_15_0 plaintext_31_0 -rot_0_0_15_1 -modadd_0_1_15_0', - 'rot_0_0_15_0 plaintext_31_0 -plaintext_31_1 -modadd_0_1_15_0', + 'rot_0_0_15_1 modadd_0_1_15_0 modadd_0_1_15_1 -plaintext_31_1', + 'plaintext_31_1 modadd_0_1_15_0 modadd_0_1_15_1 -rot_0_0_15_1', 'modadd_0_1_15_0 -rot_0_0_15_1 -plaintext_31_1 -modadd_0_1_15_1']) """ in_ids_0, in_ids_1 = self._generate_input_double_ids() diff --git a/claasp/components/multi_input_non_linear_logical_operator_component.py b/claasp/components/multi_input_non_linear_logical_operator_component.py index c6edf30d..e0a02d63 100644 --- a/claasp/components/multi_input_non_linear_logical_operator_component.py +++ b/claasp/components/multi_input_non_linear_logical_operator_component.py @@ -242,9 +242,9 @@ def milp_xor_differential_propagation_constraints(self, model): EXAMPLES:: sage: from claasp.ciphers.block_ciphers.simon_block_cipher import SimonBlockCipher - sage: from claasp.cipher_modules.models.milp.milp_model import MilpModel + sage: from claasp.cipher_modules.models.milp.milp_models.milp_xor_differential_model import MilpXorDifferentialModel sage: simon = SimonBlockCipher(block_bit_size=32, key_bit_size=64, number_of_rounds=2) - sage: milp = MilpModel(simon) + sage: milp = MilpXorDifferentialModel(simon) sage: milp.init_model_in_sage_milp_class() sage: and_component = simon.get_component_from_id("and_0_4") sage: variables, constraints = and_component.milp_xor_differential_propagation_constraints(milp) @@ -300,9 +300,9 @@ def milp_xor_linear_mask_propagation_constraints(self, model): EXAMPLES:: sage: from claasp.ciphers.block_ciphers.simon_block_cipher import SimonBlockCipher - sage: from claasp.cipher_modules.models.milp.milp_model import MilpModel + sage: from claasp.cipher_modules.models.milp.milp_models.milp_xor_linear_model import MilpXorLinearModel sage: simon = SimonBlockCipher(block_bit_size=32, key_bit_size=64, number_of_rounds=2) - sage: milp = MilpModel(simon) + sage: milp = MilpXorLinearModel(simon) sage: milp.init_model_in_sage_milp_class() sage: and_component = simon.get_component_from_id("and_0_4") sage: variables, constraints = and_component.milp_xor_linear_mask_propagation_constraints(milp) diff --git a/claasp/components/or_component.py b/claasp/components/or_component.py index 372130df..8a739614 100644 --- a/claasp/components/or_component.py +++ b/claasp/components/or_component.py @@ -173,14 +173,18 @@ def cp_xor_linear_mask_propagation_constraints(self, model): sage: gift = GiftPermutation() sage: or_component = gift.component_from(39, 6) sage: cp = CpModel(gift) - sage: or_component.cp_xor_linear_mask_propagation_constraints(cp) - (['array[0..31] of var int: p_or_39_6;', - 'array[0..63] of var 0..1:or_39_6_i;', - 'array[0..31] of var 0..1:or_39_6_o;'], - ['constraint table(or_39_6_i[0]++or_39_6_i[32]++or_39_6_o[0]++p_or_39_6[0],and2inputs_LAT);', - ... - 'constraint table(or_39_6_i[31]++or_39_6_i[63]++or_39_6_o[31]++p_or_39_6[31],and2inputs_LAT);', - 'constraint p[0] = sum(p_or_39_6);']) + sage: declarations, constraints = or_component.cp_xor_linear_mask_propagation_constraints(cp) + sage: declarations + ['array[0..31] of var 0..3200: p_or_39_6;', + 'array[0..63] of var 0..1:or_39_6_i;', + 'array[0..31] of var 0..1:or_39_6_o;'] + sage: constraints + ['constraint table([or_39_6_i[0]]++[or_39_6_i[32]]++[or_39_6_o[0]]++[p_or_39_6[0]],and2inputs_LAT);', + 'constraint table([or_39_6_i[1]]++[or_39_6_i[33]]++[or_39_6_o[1]]++[p_or_39_6[1]],and2inputs_LAT);', + ... + 'constraint table([or_39_6_i[31]]++[or_39_6_i[63]]++[or_39_6_o[31]]++[p_or_39_6[31]],and2inputs_LAT);', + 'constraint p[0] = sum(p_or_39_6);'] + """ input_size = int(self.input_bit_size) output_size = int(self.output_bit_size) diff --git a/claasp/components/sbox_component.py b/claasp/components/sbox_component.py index 5e9afd64..f070da39 100644 --- a/claasp/components/sbox_component.py +++ b/claasp/components/sbox_component.py @@ -255,7 +255,8 @@ def algebraic_polynomials(self, model): sage: fancy = FancyBlockCipher(number_of_rounds=1) sage: sbox_component = fancy.component_from(0, 0) sage: algebraic = AlgebraicModel(fancy) - sage: sbox_component.algebraic_polynomials(algebraic) + sage: algebraic_polynomials = sbox_component.algebraic_polynomials(algebraic) + sage: algebraic_polynomials [sbox_0_0_y2 + sbox_0_0_x1, sbox_0_0_x0*sbox_0_0_y0 + sbox_0_0_x0*sbox_0_0_x3, ... @@ -444,13 +445,10 @@ def cp_deterministic_truncated_xor_differential_constraints(self, sbox_mant, inv sage: from claasp.ciphers.block_ciphers.aes_block_cipher import AESBlockCipher sage: aes = AESBlockCipher(number_of_rounds=3) sage: sbox_component = aes.component_from(0, 1) - sage: sbox_component.cp_deterministic_truncated_xor_differential_constraints() - ([], - ['constraint table(xor_0_0[0]++xor_0_0[1]++xor_0_0[2]++xor_0_0[3]++xor_0_0[4]++xor_0_0[5]++xor_0_0[6]++xor_0_0[7]++' - '[sbox_0_1[0]]++[sbox_0_1[1]]++[sbox_0_1[2]]++[sbox_0_1[3]]++[sbox_0_1[4]]++[sbox_0_1[5]]++[sbox_0_1[6]]++[sbox_0_1[7]], ' - '0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,2,2,2,2,2,2' - '...' - '2,2,0,2,1,2,1,2,2,2,2,2,2,2,2,2,1,0,2,2,1,2,2,2,2,2,2,2,2,2,2,2);']) + sage: declarations, constraints, sbox_mant = sbox_component.cp_deterministic_truncated_xor_differential_constraints(sbox_mant = []) + sage: constraints + ['constraint table([xor_0_0[0]]++[xor_0_0[1]]++[xor_0_0[2]]++[xor_0_0[3]]++[xor_0_0[4]]++[xor_0_0[5]]++[xor_0_0[6]]++[xor_0_0[7]]++[sbox_0_1[0]]++[sbox_0_1[1]]++[sbox_0_1[2]]++[sbox_0_1[3]]++[sbox_0_1[4]]++[sbox_0_1[5]]++[sbox_0_1[6]]++[sbox_0_1[7]], table_sbox_0_1);'] + """ input_id_links = self.input_id_links output_id_link = self.id @@ -761,27 +759,28 @@ def milp_large_xor_differential_probability_constraints(self, binary_variable, i EXAMPLES:: - sage: from claasp.ciphers.block_ciphers.aes_block_cipher import AESBlockCipher + sage: from claasp.ciphers.block_ciphers.present_block_cipher import PresentBlockCipher sage: from claasp.cipher_modules.models.milp.milp_model import MilpModel sage: from sage.crypto.sbox import SBox - sage: aes = AESBlockCipher(number_of_rounds=3) - sage: milp = MilpModel(aes) + sage: present = PresentBlockCipher(number_of_rounds=3) + sage: milp = MilpModel(present) sage: milp.init_model_in_sage_milp_class() - sage: sbox_component = aes.component_from(0, 1) + sage: sbox_component = present.component_from(0, 1) sage: from claasp.cipher_modules.models.milp.utils.generate_inequalities_for_large_sboxes import delete_dictionary_that_contains_inequalities_for_large_sboxes sage: delete_dictionary_that_contains_inequalities_for_large_sboxes() - sage: variables, constraints = sbox_component.milp_large_xor_differential_probability_constraints(milp.binary_variable, milp.integer_variable, milp._non_linear_component_id) # long + sage: variables, constraints = sbox_component.milp_large_xor_differential_probability_constraints(milp.binary_variable, milp.integer_variable, milp._non_linear_component_id) ... - sage: variables # long - [('x[xor_0_0_0]', x_0), - ('x[xor_0_0_1]', x_1), - ... - ('x[sbox_0_1_6]', x_14), - ('x[sbox_0_1_7]', x_15)] - sage: constraints[:3] # long - [x_0 + x_1 + x_2 + x_3 + x_4 + x_5 + x_6 + x_7 <= 8*x_16, - 1 - x_0 - x_1 - x_2 - x_3 - x_4 - x_5 - x_6 - x_7 <= 8 - 8*x_16, - x_8 <= x_16] + sage: variables + [('x[xor_0_0_0]', x_0), + ('x[xor_0_0_1]', x_1), + ... + ('x[sbox_0_1_2]', x_6), + ('x[sbox_0_1_3]', x_7)] + sage: constraints[:3] + [x_0 + x_1 + x_2 + x_3 <= 4*x_8, + 1 - x_0 - x_1 - x_2 - x_3 <= 4 - 4*x_8, + x_4 <= x_8] + """ x = binary_variable @@ -865,9 +864,9 @@ def milp_small_xor_differential_probability_constraints(self, binary_variable, i """ Return a list of variables and a list of constrains modeling a component of type SBOX. - .. NOTE:: + NOTE:: - This is for MILP small xor differential probability. Constraints extracted from + This is for MILP small xor differential probability. Constraints extracted from https://eprint.iacr.org/2014/747.pdf and https://tosc.iacr.org/index.php/ToSC/article/view/805/759 INPUT: @@ -895,10 +894,10 @@ def milp_small_xor_differential_probability_constraints(self, binary_variable, i ('x[sbox_0_1_3]', x_7)] sage: constraints [x_8 <= x_0 + x_1 + x_2 + x_3, - x_0 <= x_8, - ... - x_9 + x_10 == x_8, - x_11 == 30*x_9 + 20*x_10] + x_0 <= x_8, + ... + x_9 + x_10 == x_8, + x_11 == 300*x_9 + 200*x_10] """ x = binary_variable @@ -1042,13 +1041,12 @@ def milp_xor_differential_propagation_constraints(self, model): EXAMPLES:: sage: from claasp.ciphers.block_ciphers.present_block_cipher import PresentBlockCipher - sage: from claasp.cipher_modules.models.milp.milp_model import MilpModel + sage: from claasp.cipher_modules.models.milp.milp_models.milp_xor_differential_model import MilpXorDifferentialModel sage: present = PresentBlockCipher(number_of_rounds=6) - sage: milp = MilpModel(present) + sage: milp = MilpXorDifferentialModel(present) sage: milp.init_model_in_sage_milp_class() sage: sbox_component = present.component_from(0, 1) sage: variables, constraints = sbox_component.milp_xor_differential_propagation_constraints(milp) - ... sage: variables [('x[xor_0_0_0]', x_0), ('x[xor_0_0_1]', x_1), @@ -1060,7 +1058,7 @@ def milp_xor_differential_propagation_constraints(self, model): 1 - x_0 - x_1 - x_2 - x_3 <= 4 - 4*x_8, ... x_9 + x_10 == x_8, - x_11 == 30*x_9 + 20*x_10] + x_11 == 300*x_9 + 200*x_10] """ binary_variable = model.binary_variable integer_variable = model.integer_variable @@ -1084,9 +1082,9 @@ def milp_xor_linear_mask_propagation_constraints(self, model): EXAMPLES:: sage: from claasp.ciphers.block_ciphers.present_block_cipher import PresentBlockCipher - sage: from claasp.cipher_modules.models.milp.milp_model import MilpModel + sage: from claasp.cipher_modules.models.milp.milp_models.milp_xor_linear_model import MilpXorLinearModel sage: present = PresentBlockCipher(number_of_rounds=6) - sage: milp = MilpModel(present) + sage: milp = MilpXorLinearModel(present) sage: milp.init_model_in_sage_milp_class() sage: sbox_component = present.component_from(0, 1) sage: variables, constraints = sbox_component.milp_xor_linear_mask_propagation_constraints(milp) @@ -1098,8 +1096,8 @@ def milp_xor_linear_mask_propagation_constraints(self, model): ('x[sbox_0_1_2_o]', x_6), ('x[sbox_0_1_3_o]', x_7)] sage: constraints - [x_8 <= x_4 + x_5 + x_6 + x_7, - x_0 <= x_8, + [x_0 + x_1 + x_2 + x_3 <= 4*x_8, + 1 - x_0 - x_1 - x_2 - x_3 <= 4 - 4*x_8, ... x_9 + x_10 + x_11 + x_12 == x_8, x_13 == 200*x_9 + 100*x_10 + 100*x_11 + 200*x_12] @@ -1122,11 +1120,17 @@ def milp_wordwise_deterministic_truncated_xor_differential_constraints(self, mod 6 inequalities can enforce these transitions. They can either be computer using Sage with the Polyhedron class - sage: valid_points = [[0,0,0,0], [0,1,1,0],[1,0,1,0],[1,1,1,1]] - sage: from sage.geometry.polyhedron.constructor import Polyhedron - sage: Polyhedron(vertices=valid_points) - sage: for inequality in poly.Hrepresentation(): - ....: print(f'{inequality.repr_pretty()}') + + sage: valid_points = [[0,0,0,0], [0,1,1,0],[1,0,1,0],[1,1,1,1]] + sage: from sage.geometry.polyhedron.constructor import Polyhedron + sage: poly = Polyhedron(vertices=valid_points) + sage: for inequality in poly.Hrepresentation(): + ....: print(f'{inequality.repr_pretty()}') + x0 + x1 - x2 - x3 == 0 + x3 >= 0 + x0 - x3 >= 0 + x1 - x3 >= 0 + -x0 - x1 + x3 >= -1 or using espresso @@ -1152,10 +1156,9 @@ def milp_wordwise_deterministic_truncated_xor_differential_constraints(self, mod sage: constraints [x_0 + x_1 <= 1 + x_3, x_2 <= x_0 + x_1, - ... + ... x_1 <= x_2, x_0 <= x_2] - """ x = model.binary_variable @@ -1296,6 +1299,7 @@ def milp_undisturbed_bits_bitwise_deterministic_truncated_xor_differential_const sage: milp.init_model_in_sage_milp_class() sage: sbox_component = present.component_from(0,1) sage: variables, constraints = sbox_component.milp_undisturbed_bits_bitwise_deterministic_truncated_xor_differential_constraints(milp) + ... sage: variables [('x[xor_0_0_0_class_bit_0]', x_0), ('x[xor_0_0_0_class_bit_1]', x_1), @@ -1316,8 +1320,7 @@ def milp_undisturbed_bits_bitwise_deterministic_truncated_xor_differential_const sage: milp.init_model_in_sage_milp_class() sage: sbox_component = ascon.component_from(0, 3) sage: variables, constraints = sbox_component.milp_undisturbed_bits_bitwise_deterministic_truncated_xor_differential_constraints(milp) - - + ... """ x = model.binary_variable diff --git a/claasp/components/xor_component.py b/claasp/components/xor_component.py index a4218d60..ac108ebc 100644 --- a/claasp/components/xor_component.py +++ b/claasp/components/xor_component.py @@ -641,8 +641,8 @@ def milp_bitwise_deterministic_truncated_xor_differential_binary_constraints(sel EXAMPLES:: 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_models.milp_bitwise_deterministic_truncated_xor_differential_model import MilpBitwiseDeterministicTruncatedXorDifferentialModel + sage: cipher = SimonBlockCipher(block_bit_size=32, key_bit_size=64, number_of_rounds=2) sage: milp = MilpBitwiseDeterministicTruncatedXorDifferentialModel(cipher) sage: milp.init_model_in_sage_milp_class() sage: xor_component = cipher.get_component_from_id("xor_0_5") @@ -654,8 +654,8 @@ def milp_bitwise_deterministic_truncated_xor_differential_binary_constraints(sel ('x[xor_0_5_15_class_bit_0]', x_94), ('x[xor_0_5_15_class_bit_1]', x_95)] sage: constraints - [1 <= 1 - x_1 + x_33 + x_64 + x_65, - 1 <= 1 + x_1 - x_33 + x_64 + x_65, + [x_96 == 2*x_0 + x_1, + x_97 == 2*x_2 + x_3, ... 1 <= 1 - x_30 + x_94, 1 <= 2 - x_62 - x_63] @@ -668,7 +668,8 @@ def milp_bitwise_deterministic_truncated_xor_differential_binary_constraints(sel input_id_tuples, output_id_tuples = self._get_input_output_variables_tuples() input_ids, output_ids = self._get_input_output_variables() - variables = [(f"x[{var_elt}]", x[var_elt]) for var_tuple in input_id_tuples + output_id_tuples for var_elt in var_tuple] + variables = [(f"x[{var_elt}]", x[var_elt]) for var_tuple in input_id_tuples + output_id_tuples for var_elt in + var_tuple] linking_constraints = model.link_binary_tuples_to_integer_variables(input_id_tuples + output_id_tuples, input_ids + output_ids) @@ -678,10 +679,11 @@ def milp_bitwise_deterministic_truncated_xor_differential_binary_constraints(sel for i, output_id in enumerate(output_id_tuples): result_ids = [(f'temp_xor_{j}_{self.id}_{i}_0', f'temp_xor_{j}_{self.id}_{i}_1') for j in range(number_of_inputs - 2)] + [output_id] - constraints.extend(milp_utils.milp_xor_truncated(model, input_id_tuples[i::output_bit_size][0], input_id_tuples[i::output_bit_size][1], result_ids[0])) + constraints.extend(milp_utils.milp_xor_truncated(model, input_id_tuples[i::output_bit_size][0], + input_id_tuples[i::output_bit_size][1], result_ids[0])) for chunk in range(1, number_of_inputs - 1): - constraints.extend(milp_utils.milp_xor_truncated(model, input_id_tuples[i::output_bit_size][chunk + 1], result_ids[chunk - 1], result_ids[chunk])) - + constraints.extend(milp_utils.milp_xor_truncated(model, input_id_tuples[i::output_bit_size][chunk + 1], + result_ids[chunk - 1], result_ids[chunk])) return variables, constraints @@ -756,7 +758,6 @@ def milp_bitwise_deterministic_truncated_xor_differential_constraints(self, mode return variables, constraints - def milp_wordwise_deterministic_truncated_xor_differential_constraints(self, model): """ Returns a list of variables and a list of constraints for XOR component @@ -801,6 +802,9 @@ def milp_wordwise_deterministic_truncated_xor_differential_constraints(self, mod 1 <= 2 - x_30 - x_39] """ + if model.word_size == 8: + return self.milp_wordwise_deterministic_truncated_xor_differential_sequential_constraints(model) + x = model.binary_variable num_of_inputs = int(self.description[1]) @@ -824,7 +828,6 @@ def milp_wordwise_deterministic_truncated_xor_differential_constraints(self, mod return variables, constraints - def milp_wordwise_deterministic_truncated_xor_differential_sequential_constraints(self, model): """ Returns a list of variables and a list of constraints for XOR component @@ -845,20 +848,20 @@ def milp_wordwise_deterministic_truncated_xor_differential_sequential_constraint sage: from claasp.cipher_modules.models.milp.milp_models.milp_wordwise_deterministic_truncated_xor_differential_model import MilpWordwiseDeterministicTruncatedXorDifferentialModel sage: milp = MilpWordwiseDeterministicTruncatedXorDifferentialModel(cipher) sage: milp.init_model_in_sage_milp_class() - sage: xor_component = cipher.get_component_from_id("xor_0_32") + sage: xor_component = cipher.get_component_from_id("xor_0_31") sage: variables, constraints = xor_component.milp_wordwise_deterministic_truncated_xor_differential_sequential_constraints(milp) sage: variables - [('x[xor_0_31_word_0_class_bit_0]', x_0), - ('x[xor_0_31_word_0_class_bit_1]', x_1), + [('x[sbox_0_26_word_0_class_bit_0]', x_0), + ('x[sbox_0_26_word_0_class_bit_1]', x_1), ... - ('x[xor_0_32_30]', x_118), - ('x[xor_0_32_31]', x_119)] + ('x[xor_0_31_30]', x_158), + ('x[xor_0_31_31]', x_159)] sage: constraints - [1 <= 1 + x_0 + x_2 + x_3 + x_4 + x_5 + x_6 + x_7 + x_8 + x_9 + x_41 - x_81, - 1 <= 1 + x_1 + x_40 + x_42 + x_43 + x_44 + x_45 + x_46 + x_47 + x_48 + x_49 - x_81, + [1 <= 1 + x_0 + x_2 + x_3 + x_4 + x_5 + x_6 + x_7 + x_8 + x_9 + x_41 - x_161, + 1 <= 1 + x_1 + x_40 + x_42 + x_43 + x_44 + x_45 + x_46 + x_47 + x_48 + x_49 - x_161, ... - 1 <= 1 + x_31 - x_39, - 1 <= 2 - x_30 - x_39] + 1 <= 1 + x_111 - x_119, + 1 <= 2 - x_110 - x_119] """ @@ -895,9 +898,9 @@ def milp_wordwise_deterministic_truncated_xor_differential_simple_constraints(se It follows a simplified model: if dX0 + dX1 > 2 then dY = 3 - elif dX0<2 /\ dX1<2 - then zeta Y = zetaX0 ^ zetaX1 - else dY = 2 + elif dX0<2 / dX1<2 + then zeta Y = zetaX0 ^ zetaX1 + else dY = 2 INPUTS: @@ -921,7 +924,6 @@ def milp_wordwise_deterministic_truncated_xor_differential_simple_constraints(se input_class_vars, output_class_vars = self._get_wordwise_input_output_linked_class(model) - variables = [(f"x_class[{var}]", x_class[var]) for var in input_class_vars + output_class_vars] constraints = [] @@ -929,7 +931,6 @@ def milp_wordwise_deterministic_truncated_xor_differential_simple_constraints(se input_vars = [x_class[var] for var in input_class_vars] output_vars = [x_class[var] for var in output_class_vars] - for i in range(len(output_class_vars)): input_words = input_vars[i::len(output_class_vars)] input_a = input_words[0] @@ -939,12 +940,12 @@ def milp_wordwise_deterministic_truncated_xor_differential_simple_constraints(se then_constraints_list = [] # if dX0 + dX1 > 2 then dY = 3 - a_b_greater_2, geq_2_constraints = milp_utils.milp_geq(model, input_a + input_b, 2, 2 * model._model.get_max(x_class) + 1) + a_b_greater_2, geq_2_constraints = milp_utils.milp_geq(model, input_a + input_b, 2, + 2 * model._model.get_max(x_class) + 1) var_if_list.append(a_b_greater_2) constraints.extend(geq_2_constraints) then_constraints_list.append([output_c == 3]) - # elif dX0 < 2 /\ dX1 < 2 then zeta Y = zetaX0 ^ zetaX1 a_less_2, a_less_2_constraints = milp_utils.milp_less(model, input_a, 2, model._model.get_max(x_class) + 1) b_less_2, b_less_2_constraints = milp_utils.milp_less(model, input_a, 2, model._model.get_max(x_class) + 1) @@ -960,11 +961,11 @@ def milp_wordwise_deterministic_truncated_xor_differential_simple_constraints(se # else dY = 2 else_constraints = [output_c == 2] - constraints.extend(milp_utils.milp_if_elif_else(model, var_if_list, then_constraints_list, else_constraints, num_of_inputs * model._model.get_max(x_class))) + constraints.extend(milp_utils.milp_if_elif_else(model, var_if_list, then_constraints_list, else_constraints, + num_of_inputs * model._model.get_max(x_class))) return variables, constraints - def minizinc_constraints(self, model): r""" Return variables and constraints for the XOR component for MINIZINC CIPHER model. diff --git a/claasp/editor.py b/claasp/editor.py index a213bbd8..af507cf0 100644 --- a/claasp/editor.py +++ b/claasp/editor.py @@ -275,9 +275,9 @@ def add_FSR_component(cipher, input_id_links, input_bit_positions, output_bit_si sage: cipher = Cipher("cipher_name", "fsr", ["input"], [12], 12) sage: cipher.add_round() sage: fsr_0_0 = cipher.add_FSR_component(["input", "input"], [[0,1,2,3,4],[0,1,2,3,4,5,6]], 12, [[ - [5, [[4], [5], [6, 7]]], # Register_len:5, feedback poly: x4 + x5 + x6*x7 - [7, [[0], [8], [1, 2]]] # Register_len:7, feedback poly: x0 + x1*x2 + x8 - ], 1]) + ....: [5, [[4], [5], [6, 7]]], # Register_len:5, feedback poly: x4 + x5 + x6*x7 + ....: [7, [[0], [8], [1, 2]]] # Register_len:7, feedback poly: x0 + x1*x2 + x8 + ....: ], 1]) sage: cipher.print() cipher_id = cipher_name_i12_o12_r1 cipher_type = fsr @@ -285,7 +285,6 @@ def add_FSR_component(cipher, input_id_links, input_bit_positions, output_bit_si cipher_inputs_bit_size = [12] cipher_output_bit_size = 12 cipher_number_of_rounds = 1 - # round = 0 - round component = 0 id = fsr_0_0 @@ -479,7 +478,7 @@ def add_MODADD_component(cipher, input_id_links, input_bit_positions, output_bit input_id_link = ['input', 'input'] input_bit_positions = [[0, 1], [2, 3]] output_bit_size = 2 - description = ['MODADD', 2] + description = ['MODADD', 2, None] cipher_reference_code = None """ if cipher.current_round_number is None: @@ -524,7 +523,7 @@ def add_MODSUB_component(cipher, input_id_links, input_bit_positions, output_bit input_id_link = ['input', 'input'] input_bit_positions = [[0, 1], [2, 3]] output_bit_size = 2 - description = ['MODSUB', 2] + description = ['MODSUB', 2, None] cipher_reference_code = None """ if cipher.current_round_number is None: @@ -792,7 +791,7 @@ def add_round(cipher): # round 0 [ ], - ], + ], 'cipher_reference_code': None, } """ @@ -1633,7 +1632,12 @@ def remove_rotations(cipher): sage: removed_rotations_speck = remove_rotations(speck) sage: removed_rotations_speck.print_as_python_dictionary() cipher = { - ... + 'cipher_id': 'speck_p32_k64_o32_r5', + 'cipher_type': 'block_cipher', + 'cipher_inputs': ['plaintext', 'key'], + 'cipher_inputs_bit_size': [32, 64], + 'cipher_output_bit_size': 32, + 'cipher_number_of_rounds': 5, 'cipher_rounds' : [ # round 0 [ @@ -1645,31 +1649,70 @@ def remove_rotations(cipher): 'input_id_link': ['plaintext', 'plaintext'], 'input_bit_positions': [[9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8], [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]], 'output_bit_size': 16, - 'description': ['MODADD', 2], + 'description': ['MODADD', 2, None], }, + ... + ], + # round 1 + [ { - # round = 0 - round component = 1 - 'id': 'xor_0_2', - 'type': 'word_operation', - 'input_bit_size': 32, - 'input_id_link': ['modadd_0_1', 'key'], - 'input_bit_positions': [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63]], + # round = 1 - round component = 0 + 'id': 'constant_1_0', + 'type': 'constant', + 'input_bit_size': 0, + 'input_id_link': [''], + 'input_bit_positions': [[]], 'output_bit_size': 16, - 'description': ['XOR', 2], + 'description': ['0x0000'], }, + ... + ], + # round 2 + [ { - # round = 0 - round component = 2 - 'id': 'xor_0_4', - 'type': 'word_operation', - 'input_bit_size': 32, - 'input_id_link': ['xor_0_2', 'plaintext'], - 'input_bit_positions': [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17]], + # round = 2 - round component = 0 + 'id': 'constant_2_0', + 'type': 'constant', + 'input_bit_size': 0, + 'input_id_link': [''], + 'input_bit_positions': [[]], 'output_bit_size': 16, - 'description': ['XOR', 2], + 'description': ['0x0001'], }, ... + ], + # round 3 + [ + { + # round = 3 - round component = 0 + 'id': 'constant_3_0', + 'type': 'constant', + 'input_bit_size': 0, + 'input_id_link': [''], + 'input_bit_positions': [[]], + 'output_bit_size': 16, + 'description': ['0x0002'], + }, + ... + ], + # round 4 + [ + { + # round = 4 - round component = 0 + 'id': 'constant_4_0', + 'type': 'constant', + 'input_bit_size': 0, + 'input_id_link': [''], + 'input_bit_positions': [[]], + 'output_bit_size': 16, + 'description': ['0x0003'], + }, + ... + ], + ], 'cipher_reference_code': None, } + """ cipher_without_rotations = propagate_rotations(cipher) for round_ in cipher.rounds_as_list: diff --git a/claasp/utils/utils.py b/claasp/utils/utils.py index 005a9517..d4b396c2 100644 --- a/claasp/utils/utils.py +++ b/claasp/utils/utils.py @@ -324,11 +324,23 @@ def pprint_dictionary(dictionary): EXAMPLES:: sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher + sage: from claasp.utils.utils import pprint_dictionary sage: speck = SpeckBlockCipher(block_bit_size=16, key_bit_size=32, number_of_rounds=5) sage: from claasp.cipher_modules.avalanche_tests import AvalancheTests sage: test = AvalancheTests(speck) sage: d = test.avalanche_tests(number_of_samples=100) sage: pprint_dictionary(d["test_results"]["plaintext"]["round_output"]["avalanche_dependence_vectors"][0]) + { 'component_ids': [ 'intermediate_output_0_6', + 'intermediate_output_1_12', + 'intermediate_output_2_12', + 'intermediate_output_3_12'], + 'input_difference_value': '0x1', + 'satisfied_criterion': [False, False, False, False], + 'total': [2, 1, 12, 13], + 'vectors': [ [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], + [1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0], + [1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]]} """ pp = pprint.PrettyPrinter(indent=4) @@ -346,23 +358,18 @@ def pprint_dictionary_to_file(dictionary, name_file): EXAMPLES:: - sage: from claasp.ciphers.block_ciphers.identity_block_cipher import IdentityBlockCipher + sage: from claasp.ciphers.block_ciphers.speck_block_cipher import SpeckBlockCipher sage: from claasp.utils.utils import pprint_dictionary_to_file - sage: cipher = IdentityBlockCipher() - sage: tests_configuration = {"diffusion_tests": {"run_tests": True, "number_of_samples": 100, - ....: "run_avalanche_dependence": True, "run_avalanche_dependence_uniform": True, - ....: "run_avalanche_weight": True, "run_avalanche_entropy": True, - ....: "avalanche_dependence_uniform_bias": 0.2, "avalanche_dependence_criterion_threshold": 0, - ....: "avalanche_dependence_uniform_criterion_threshold":0, "avalanche_weight_criterion_threshold": 0.1, - ....: "avalanche_entropy_criterion_threshold":0.1}, "component_analysis_tests": {"run_tests": True} - ....: } + sage: from claasp.cipher_modules.avalanche_tests import AvalancheTests sage: import inspect sage: import claasp + sage: import os.path + sage: speck = SpeckBlockCipher(block_bit_size=16, key_bit_size=32, number_of_rounds=5) + sage: test = AvalancheTests(speck) + sage: d = test.avalanche_tests(number_of_samples=100) sage: tii_path = inspect.getfile(claasp) sage: tii_dir_path = os.path.dirname(tii_path) - sage: analysis = cipher.analyze_cipher(tests_configuration) - sage: pprint_dictionary_to_file(analysis['diffusion_tests']['input_parameters'], f"{tii_dir_path}/test_json") - sage: import os.path + sage: pprint_dictionary_to_file(d["input_parameters"], f"{tii_dir_path}/test_json") sage: os.path.isfile(f"{tii_dir_path}/test_json") True diff --git a/tests/unit/cipher_modules/models/milp/milp_models/milp_wordwise_deterministic_truncated_xor_differential_model_test.py b/tests/unit/cipher_modules/models/milp/milp_models/milp_wordwise_deterministic_truncated_xor_differential_model_test.py index 52b1cc01..a6aa8fe2 100644 --- a/tests/unit/cipher_modules/models/milp/milp_models/milp_wordwise_deterministic_truncated_xor_differential_model_test.py +++ b/tests/unit/cipher_modules/models/milp/milp_models/milp_wordwise_deterministic_truncated_xor_differential_model_test.py @@ -13,7 +13,7 @@ def test_build_wordwise_deterministic_truncated_xor_differential_trail_model(): milp.build_wordwise_deterministic_truncated_xor_differential_trail_model() constraints = milp.model_constraints - assert len(constraints) == 43960 + assert len(constraints) == 19768 assert str(constraints[0]) == '1 <= 1 + x_0 - x_1 + x_2 + x_3 + x_4 + x_5 + x_6 + x_7 + x_8 + x_9' assert str(constraints[1]) == '1 <= 1 + x_1 - x_9' assert str(constraints[-2]) == 'x_3062 == x_2886' diff --git a/tests/unit/cipher_modules/models/milp/milp_models/milp_wordwise_impossible_xor_differential_model_test.py b/tests/unit/cipher_modules/models/milp/milp_models/milp_wordwise_impossible_xor_differential_model_test.py index 3f0b8cd8..db07d006 100644 --- a/tests/unit/cipher_modules/models/milp/milp_models/milp_wordwise_impossible_xor_differential_model_test.py +++ b/tests/unit/cipher_modules/models/milp/milp_models/milp_wordwise_impossible_xor_differential_model_test.py @@ -15,7 +15,7 @@ def test_build_wordwise_impossible_xor_differential_trail_model(): constraints = milp.model_constraints - assert len(constraints) == 48392 + assert len(constraints) == 24200 assert str(constraints[0]) == '1 <= 1 + x_0 - x_1 + x_2 + x_3 + x_4 + x_5 + x_6 + x_7 + x_8 + x_9' assert str(constraints[1]) == '1 <= 1 + x_1 - x_9' assert str(constraints[-2]) == 'x_3238 == x_2065' diff --git a/tests/unit/cipher_modules/models/milp/utils/generate_inequalities_for_wordwise_truncated_xor_with_n_input_bits_test.py b/tests/unit/cipher_modules/models/milp/utils/generate_inequalities_for_wordwise_truncated_xor_with_n_input_bits_test.py index 8c8e3a63..c9f29e81 100644 --- a/tests/unit/cipher_modules/models/milp/utils/generate_inequalities_for_wordwise_truncated_xor_with_n_input_bits_test.py +++ b/tests/unit/cipher_modules/models/milp/utils/generate_inequalities_for_wordwise_truncated_xor_with_n_input_bits_test.py @@ -22,5 +22,5 @@ def test_generate_valid_points_for_xor_between_n_input_words(): def test_update_dictionary_that_contains_wordwise_truncated_xor_inequalities_between_n_inputs(): update_dictionary_that_contains_wordwise_truncated_xor_inequalities_between_n_inputs(3, 3) dictio = output_dictionary_that_contains_wordwise_truncated_xor_inequalities() - assert dictio[3][3][:2] == ['1----1----------0---', '--100--100-0----1---'] - assert dictio[3][3][-2:] == ['------01------------', '----------1----0----'] \ No newline at end of file + assert dictio[3][3][:2] == ['0-000-0---00----1---', '0-00000----0----1---'] + assert dictio[3][3][-2:] == ['-----1---------0----', '1--------------0----'] \ No newline at end of file diff --git a/tests/unit/components/linear_layer_component_test.py b/tests/unit/components/linear_layer_component_test.py index aa7773d8..6aeab34c 100644 --- a/tests/unit/components/linear_layer_component_test.py +++ b/tests/unit/components/linear_layer_component_test.py @@ -325,8 +325,8 @@ def test_milp_wordwise_deterministic_truncated_xor_differential_constraints(): assert str(constraints[0]) == '1 <= 1 + x_6 + x_8 + x_9 + x_10 + x_11 + x_13 + x_18 + x_19 - x_25' assert str(constraints[1]) == '1 <= 1 + x_6 + x_8 + x_9 + x_10 + x_11 + x_12 + x_13 + x_19 - x_25' - assert str(constraints[-2]) == '1 <= 2 - x_6 - x_8' - assert str(constraints[-1]) == '1 <= 1 + x_7 - x_8' + assert str(constraints[-2]) == '1 <= 1 + x_7 - x_8' + assert str(constraints[-1]) == '1 <= 1 + x_1 - x_2' cipher = AESBlockCipher(number_of_rounds=2) cipher_inverse = cipher.cipher_inverse()