Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/remove cipher from report class #194

Closed
wants to merge 38 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
7193478
Fixing tests
juaninf Mar 5, 2024
d2eaf35
Merge branch 'develop' into differential_checker_test_for_speck
juaninf Mar 5, 2024
6ea1f40
FIX: Typo in show() method of Report class
p-huynh Mar 7, 2024
5057af1
Added cast to int to fix issue where the functions are called with sa…
Mar 7, 2024
5e54675
updated report class with QoL changes
MFormenti Mar 7, 2024
aead137
updated report class with QoL changes
MFormenti Mar 7, 2024
07fdc4d
Merge pull request #179 from Crypto-TII/fix/integer_cast_issue
peacker Mar 7, 2024
f0cc095
updated report class with QoL changes
MFormenti Mar 7, 2024
7126c36
updated report class with QoL changes
MFormenti Mar 7, 2024
983f93f
updated report class with QoL changes
MFormenti Mar 7, 2024
04ca5ec
updated report class with QoL changes
MFormenti Mar 8, 2024
32bec6b
Merge pull request #181 from Crypto-TII/differential_checker_test_for…
peacker Mar 8, 2024
8dff6b7
Merge pull request #178 from Crypto-TII/fix/trail_printing_in_report_…
peacker Mar 8, 2024
e7606ec
updated report class with QoL changes
MFormenti Mar 8, 2024
e0c5cf4
updated report class with QoL changes
MFormenti Mar 8, 2024
2604229
Merge branch 'develop' into fix/quality_of_life_improvements
MFormenti Mar 8, 2024
ee846e4
Merge pull request #180 from Crypto-TII/fix/quality_of_life_improvements
peacker Mar 8, 2024
3ecf30b
Refactor: refactor StatisticalTests class to NISTStatisticalTests class
Mar 8, 2024
71233fa
Refactor: refactor methods in DieharderTests from public to private
Mar 8, 2024
80066c9
Fix: adding '.txt' extension for the temporarily file used by numpy.t…
Mar 8, 2024
b74067a
display xor components, and nicer display of the radar charts
SiMohamedRachidi Mar 8, 2024
1085092
Merge pull request #185 from Crypto-TII/fix/rename_nist_statistical_t…
peacker Mar 8, 2024
221bfb6
Merge pull request #186 from Crypto-TII/fix_ascon_component_analysis
peacker Mar 8, 2024
4473624
fixed polynomial generation of moddadd based ciphers and algberaic te…
Mar 8, 2024
298ce82
added some error messages for components whose polynomial generation …
Mar 9, 2024
668e8d3
fix a test timeout limit
Mar 9, 2024
df0f4be
removed some redundant lines
Mar 9, 2024
5f9e639
polished code to improve the coverage
Mar 10, 2024
da12ae2
Merge pull request #187 from Crypto-TII/fix/poly-gen-modadd-based-cip…
peacker Mar 10, 2024
f2565f9
FIX:Fixed typo in dieharder_statistical_tests
MFormenti Mar 11, 2024
2c2d5e6
Merge pull request #188 from Crypto-TII/fix/fix-dieharder-file-extension
peacker Mar 11, 2024
d0d5707
FIX:reworked test outputs to include cipher object. changed str repre…
MFormenti Mar 12, 2024
c07db7f
removed cipher from report class creator
MFormenti Mar 12, 2024
fcfbdff
removed cipher from report class creator
MFormenti Mar 12, 2024
2d77047
refactored pytests
MFormenti Mar 12, 2024
755b4bd
refactored pytests
MFormenti Mar 12, 2024
83c02c2
refactored pytests
MFormenti Mar 12, 2024
c5f6d48
refactored pytests
MFormenti Mar 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions claasp/cipher.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@


class Cipher:


def __init__(self, family_name, cipher_type, cipher_inputs,
cipher_inputs_bit_size, cipher_output_bit_size,
cipher_reference_code=None):
Expand Down Expand Up @@ -146,6 +148,8 @@ def __init__(self, family_name, cipher_type, cipher_inputs,
self._id = self.make_cipher_id()
self._file_name = self.make_file_name()

def __repr__(self):
return self.id
def _are_there_not_forbidden_components(self, forbidden_types, forbidden_descriptions):
return self._rounds.are_there_not_forbidden_components(forbidden_types, forbidden_descriptions)

Expand Down
25 changes: 11 additions & 14 deletions claasp/cipher_modules/algebraic_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,24 +66,21 @@ def algebraic_tests(self, timeout=60):
nmonomials_up_to_round.append(Fseq.nmonomials())
max_deg_of_equations_up_to_round.append(Fseq.maximal_degree())

if tests_up_to_round and tests_up_to_round[-1] is True:
tests_up_to_round.append(True)
else:
from cysignals.alarm import alarm, cancel_alarm
from cysignals.alarm import alarm, cancel_alarm, AlarmInterrupt
try:
alarm(timeout)
Fseq.groebner_basis()
cancel_alarm()
result = False
except AlarmInterrupt:
result = True

try:
alarm(timeout)
cancel_alarm()
result = False
except InterruptedError:
result = True

tests_up_to_round.append(result)
tests_up_to_round.append(result)

input_parameters = {
"cipher.id": self._cipher.id,
"timeout": timeout,
"test_name": "algebraic_tests"
"test_name": "algebraic_tests",
"cipher": self._cipher
}
test_results = {
"number_of_variables": nvars_up_to_round,
Expand Down
1 change: 1 addition & 0 deletions claasp/cipher_modules/avalanche_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ def avalanche_tests(self, number_of_samples=5, avalanche_dependence_uniform_bias
avalanche_dependence_uniform_bias)
intermediate_output_names = self._add_intermediate_output_components_id_to_dictionary(self._cipher.get_all_components())
diffusion_tests = {"input_parameters": {
"cipher": self._cipher,
"test_name": "avalanche_tests",
"number_of_samples": number_of_samples,
"avalanche_dependence_uniform_bias": avalanche_dependence_uniform_bias,
Expand Down
32 changes: 18 additions & 14 deletions claasp/cipher_modules/component_analysis_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ def component_analysis_tests(self):

output_dictionary = {
'input_parameters': {
'test_name': 'component_analysis'
'test_name': 'component_analysis',
'cipher': self._cipher
},
'test_results': components_analysis
}
Expand Down Expand Up @@ -153,15 +154,19 @@ def print_component_analysis_as_radar_charts(self, results=None):
plt.rcParams['figure.figsize'] = [20, 20]

# remove XOR from results
results_without_xor = [results[i] for i in range(len(results)) if results[i]["description"][0] != "XOR"]
results = self._remove_components_with_strings_as_values(results_without_xor)
# results_without_xor = [results[i] for i in range(len(results)) if results[i]["description"][0] != "XOR"]
results_without_fsr = [results[i] for i in range(len(results)) if results[i]["type"] != "fsr"]
# removed for now because the fsr dictionary does not follow the standard structure as the other components:
# the keys properties, values, etc are not present.
# results = self._remove_components_with_strings_as_values(results_without_xor)
results = self._remove_components_with_strings_as_values(results_without_fsr)

nb_plots = len(results)
col = 2
row = nb_plots // col
if nb_plots % col != 0:
row += nb_plots % col
positions = {8: -0.7, 3: -0.4}
positions = {8: -0.7, 3: -0.4} # positions of the text according to the numbers of properties

for plot_number in range(nb_plots):
categories = list(results[plot_number]["properties"].keys())
Expand Down Expand Up @@ -211,10 +216,12 @@ def print_component_analysis_as_radar_charts(self, results=None):
self._fill_area(ax, categories, plot_number, positions, results)

# Show the graph
plt.subplots_adjust(left=0.25, bottom=0.1, right=0.7, top=0.95, wspace=0, hspace=0.96)
if nb_plots >= 5:
plt.subplots_adjust(left=0.02, bottom=0.1, right=0.7, top=0.95, wspace=1, hspace=0.96)
else:
plt.subplots_adjust(left=0.09, bottom=0.3, right=0.7, top=0.7, wspace=1, hspace=0.96)
plt.show()
#print("The radar chart can be plot with the build-in method plt.show()")

#return plt


Expand Down Expand Up @@ -274,7 +281,7 @@ def _select_boolean_function(self, component, boolean_polynomial_ring):
elif component.description[0] == "MODADD":
return self._MODADD_as_boolean_function(component, boolean_polynomial_ring)
else:
return "TODO(...)"
return f"TODO: {component.id} not implemented yet"


def _MODADD_as_boolean_function(self, component, boolean_polynomial_ring):
Expand Down Expand Up @@ -425,11 +432,8 @@ def _select_properties_function(self, boolean_polynomial_ring, operation):
if component.type == 'fsr':
return self._fsr_properties(operation)

if component.type == WORD_OPERATION:
print(f"TODO : {component.description[0]}")
return {}
else:
print(f"TODO : {component.type}")
# print(f"TODO: not implemented yet")
return {}

def _is_mds(self, component):
Expand Down Expand Up @@ -485,7 +489,6 @@ def _word_operation_properties(self, operation, boolean_polynomial_ring):
INPUT:

- ``operation`` -- **list**; a list containing:

* a component with the operation under study
* number of occurrences of the operation
* list of ids of all the components with the same underlying operation
Expand Down Expand Up @@ -642,7 +645,7 @@ def _linear_layer_properties(self, operation):
"min_possible_value": 1,
"max_possible_value": pow(2, component.input_bit_size) - 1
}
if component.input_bit_size <= 32:
if component.input_bit_size <= 64:
dictio["properties"]["differential_branch_number"] = {"value": branch_number(component, 'differential', 'bit'),
"min_possible_value": 0,
"max_possible_value": component.input_bit_size}
Expand Down Expand Up @@ -883,7 +886,8 @@ def _fill_area(self, ax, categories, plot_number, positions, results):
text += f"{category} = {int(results[plot_number]['properties'][category]['value'])} " \
f"(best is {results[plot_number]['properties'][category]['max_possible_value']}, " \
f"worst is {results[plot_number]['properties'][category]['min_possible_value']})\n"
plt.text(0, positions[len(categories)], text, transform=ax.transAxes, size="small")
# plt.text(0, positions[len(categories)], text, transform=ax.transAxes, size="small")
plt.text(2, 0, text, transform=ax.transAxes, size="small")

def _initialise_spider_plot(self, plot_number, results):
is_component_word_operation = results[plot_number]["type"] == "word_operation"
Expand Down
1 change: 1 addition & 0 deletions claasp/cipher_modules/continuous_diffusion_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ def continuous_diffusion_tests(self,
"""
continuous_diffusion_tests = {"input_parameters": {
'test_name': 'continuous_diffusion_tests',
'cipher': self.cipher,
'continuous_avalanche_factor_number_of_samples': continuous_avalanche_factor_number_of_samples,
'threshold_for_avalanche_factor': threshold_for_avalanche_factor,
'continuous_neutral_measure_beta_number_of_samples': continuous_neutral_measure_beta_number_of_samples,
Expand Down
6 changes: 5 additions & 1 deletion claasp/cipher_modules/models/algebraic/algebraic_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,11 +200,15 @@ def polynomial_system_at_round(self, r):
component_type = component.type
operation = component.description[0]
component_types = ["sbox", "linear_layer", "mix_column", "constant"]
operations = ["XOR", "AND", "OR", "SHIFT", "ROTATE", "NOT"]
operations = ["XOR", "AND", "OR", "SHIFT", "ROTATE", "NOT", "MODADD"]

if component_type in component_types or (component_type == "word_operation" and operation in operations):
polynomials += component.algebraic_polynomials(self)

elif component_type == "word_operation" and \
operation in ['ROTATE_BY_VARIABLE_AMOUNT', 'SHIFT_BY_VARIABLE_AMOUNT', 'MODSUB']:
raise ValueError(f"polynomial generation of {operation} operation is not supported at present")

return Sequence(polynomials)

def ring(self):
Expand Down
4 changes: 2 additions & 2 deletions claasp/cipher_modules/models/cp/cp_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def add_solutions_from_components_values(self, components_values, memory, model_
solver_name, solver_output, total_weight):
for i in range(len(total_weight)):
solution = convert_solver_solution_to_dictionary(
self.cipher_id,
self._cipher,
model_type,
solver_name,
solve_time,
Expand Down Expand Up @@ -458,7 +458,7 @@ def solve(self, model_type, solver_name=None):
solver_output = solver_process.stdout.splitlines()
solve_time, memory, components_values, total_weight = self._parse_solver_output(solver_output)
if components_values == {}:
solution = convert_solver_solution_to_dictionary(self.cipher_id, model_type, solver_name,
solution = convert_solver_solution_to_dictionary(self._cipher, model_type, solver_name,
solve_time, memory,
components_values, total_weight)
if 'UNSATISFIABLE' in solver_output[0]:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,6 @@ def find_lowest_weight_xor_differential_trail(self, fixed_values=[], solver_name
solution = self.solve('xor_differential_one_solution', solver_name)
solution['building_time_seconds'] = build_time
solution['test_name'] = "find_lowest_weight_xor_differential_trail"

return solution

def find_one_xor_differential_trail(self, fixed_values=[], solver_name='Chuffed'):
Expand Down
2 changes: 1 addition & 1 deletion claasp/cipher_modules/models/milp/milp_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ def solve(self, model_type, solver_name=SOLVER_DEFAULT, external_solver_name=Non
status, milp_time, milp_memory = self._solve_with_internal_solver()
objective_value, components_values = self._parse_solver_output()

solution = convert_solver_solution_to_dictionary(self.cipher_id, model_type, solver_name_in_solution, milp_time,
solution = convert_solver_solution_to_dictionary(self._cipher, model_type, solver_name_in_solution, milp_time,
milp_memory, components_values, objective_value)
solution['status'] = status
return solution
Expand Down
4 changes: 2 additions & 2 deletions claasp/cipher_modules/models/sat/sat_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ def _solve_with_external_sat_solver(self, model_type, solver_name, options, host
component2fields, total_weight = {}, None
if total_weight is not None:
total_weight = float(total_weight)
solution = convert_solver_solution_to_dictionary(self.cipher_id, model_type, solver_name, sat_time,
solution = convert_solver_solution_to_dictionary(self._cipher, model_type, solver_name, sat_time,
sat_memory, component2fields, total_weight)
solution['status'] = status

Expand All @@ -361,7 +361,7 @@ def _solve_with_sage_sat_solver(self, model_type, solver_name):
status = 'UNSATISFIABLE'
if total_weight is not None:
total_weight = float(total_weight)
solution = convert_solver_solution_to_dictionary(self.cipher_id, model_type, solver_name, sat_time,
solution = convert_solver_solution_to_dictionary(self._cipher, model_type, solver_name, sat_time,
sat_memory, component2fields, total_weight)
solution['status'] = status

Expand Down
2 changes: 1 addition & 1 deletion claasp/cipher_modules/models/smt/smt_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ def _get_data(data_string, lines):
if total_weight is not None:
total_weight = float(total_weight)

solution = convert_solver_solution_to_dictionary(self.cipher_id, model_type, solver_name, solve_time,
solution = convert_solver_solution_to_dictionary(self._cipher, model_type, solver_name, solve_time,
memory, component2attributes, total_weight)
solution['status'] = status

Expand Down
4 changes: 2 additions & 2 deletions claasp/cipher_modules/models/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def add_arcs(arcs, component, curr_input_bit_ids, input_bit_size, intermediate_o
arcs[previous_output_bit_ids[i]].append(curr_input_bit_ids[i])


def convert_solver_solution_to_dictionary(cipher_id, model_type, solver_name, solve_time, memory,
def convert_solver_solution_to_dictionary(cipher, model_type, solver_name, solve_time, memory,
components_values, total_weight):
"""
Return a dictionary that represents the solution obtained from the solver.
Expand Down Expand Up @@ -72,7 +72,7 @@ def convert_solver_solution_to_dictionary(cipher_id, model_type, solver_name, so
'total_weight': 0}
"""
return {
'cipher_id': cipher_id,
'cipher': cipher,
'model_type': model_type,
'solver_name': solver_name,
'solving_time_seconds': solve_time,
Expand Down
12 changes: 9 additions & 3 deletions claasp/cipher_modules/neural_network_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def neural_network_blackbox_distinguisher_tests(self, nb_samples=10000,
"""
results = {"input_parameters": {
"test_name": "neural_network_blackbox_distinguisher_tests",
"cipher": self.cipher,
"number_of_samples": nb_samples,
"hidden_layers": hidden_layers,
"number_of_epochs": number_of_epochs}, "test_results": {}}
Expand Down Expand Up @@ -146,7 +147,7 @@ def _update_blackbox_distinguisher_vectorized_tests_ds(self, base_inputs, base_o
# cipher_output = base_output

base_inputs_np = [np.broadcast_to(
np.array([b for b in x.to_bytes(input_lengths[i] // 8, byteorder='big')], dtype=np.uint8),
np.array([b for b in int(x).to_bytes(input_lengths[i] // 8, byteorder='big')], dtype=np.uint8),
(nb_samples, input_lengths[i] // 8)
).transpose().copy() for i, x in enumerate(base_inputs)]
random_inputs_for_index = np.frombuffer(os.urandom(nb_samples * input_lengths[index] // 8),
Expand Down Expand Up @@ -255,6 +256,7 @@ def neural_network_differential_distinguisher_tests(self, nb_samples=10000, hidd
"""
results = {"input_parameters": {
"test_name": "neural_network_differential_distinguisher_tests",
"cipher":self.cipher,
"number_of_samples": nb_samples,
"input_differences": diff,
"hidden_layers": hidden_layers,
Expand Down Expand Up @@ -313,7 +315,7 @@ def _update_distinguisher_vectorized_tests_ds(self, base_inputs, d, ds, index, l
random_labels_size = nb_samples - np.count_nonzero(np.array(labels))

base_inputs_np = [np.broadcast_to(
np.array([b for b in x.to_bytes(input_lengths[i] // 8, byteorder='big')], dtype=np.uint8),
np.array([b for b in int(x).to_bytes(input_lengths[i] // 8, byteorder='big')], dtype=np.uint8),
(nb_samples, input_lengths[i] // 8)
).transpose().copy() for i, x in enumerate(base_inputs)]
random_inputs_for_index = np.frombuffer(os.urandom(nb_samples * input_lengths[index] // 8),
Expand All @@ -323,7 +325,7 @@ def _update_distinguisher_vectorized_tests_ds(self, base_inputs, d, ds, index, l

other_inputs_np = list(base_inputs_np)

d_array = np.array([b for b in d.to_bytes(input_lengths[index] // 8, byteorder='big')])
d_array = np.array([b for b in int(d).to_bytes(input_lengths[index] // 8, byteorder='big')])
other_inputs_np[index] = other_inputs_np[index] ^ np.broadcast_to(d_array, (
nb_samples, input_lengths[index] // 8)).transpose()

Expand Down Expand Up @@ -598,6 +600,7 @@ def run_autond_pipeline(self, difference_positions=None, optimizer_samples=10 **
neural_distinguisher_test_results = {
'input_parameters': {
'test_name': 'neural_distinguisher_test',
'cipher': self.cipher,
'optimizer_samples': optimizer_samples,
'optimizer_generations': optimizer_generations,
'training_samples': training_samples,
Expand Down Expand Up @@ -636,6 +639,9 @@ def data_generator(nr, samples):
input_size = self.cipher.output_bit_size * 2
neural_network = self.get_neural_network(neural_net, input_size = input_size)
nr = max(1, highest_round-3)

neural_distinguisher_test_results['test_results']['round_start']=nr

print(f'Training {neural_net} on input difference {[hex(x) for x in input_difference]} ({self.cipher.inputs}), from round {nr}...')
neural_results = self.train_neural_distinguisher(data_generator, nr, neural_network, training_samples,
testing_samples, number_of_epochs)
Expand Down
Loading
Loading