def test_key_schedule_returns_appropriate_keys_for_256_key(aes_data): output = aes.key_schedule(aes_data['256_key']) assert np.array_equal(output, aes_data['256_key_schedule_output']) assert output.shape == (15, 16) output = aes.key_schedule( np.random.randint(0, 255, (15, 32), dtype='uint8')) assert output.shape == (15, 15, 16)
def test_dpa_on_dpa_v2(): ths = traces.read_ths_from_ets_file('tests/end_to_end/dpa_v2_sub.ets') expected_key = aes.key_schedule(key=ths[0].key)[-1] # One byte is not correctly retrieved with this configuration. expected_key[13] = 252 sf = aes.selection_functions.encrypt.DeltaRLastRounds() container = scared.Container(ths) att = scared.DPAAttack( selection_function=sf, model=scared.Monobit(7), discriminant=scared.maxabs, ) att.run(container) bit_list = range(0, 7) max_score = np.copy(att.scores) for b in bit_list: att = scared.DPAAttack(selection_function=sf, model=scared.Monobit(b), discriminant=scared.maxabs) att.run(container) max_score = np.maximum(max_score, att.scores) att.scores = max_score last_key = np.argmax(att.scores, axis=0) assert np.array_equal(expected_key, last_key)
def test_key_schedule_raise_exception_if_key_isnt_array(): with pytest.raises(TypeError): aes.key_schedule(key='foo') with pytest.raises(TypeError): aes.key_schedule(key=123456465) with pytest.raises(TypeError): aes.key_schedule(key={'shape': 12})
def test_nicv_on_dpa_v2(): ths = traces.read_ths_from_ets_file('tests/end_to_end/dpa_v2_sub.ets') expected_key = aes.key_schedule(key=ths[0].key)[-1] sf = scared.selection_functions.aes.encrypt.delta_r_last_rounds() container = scared.Container(ths[:15000]) att = scared.NICVAnalysis( selection_function=sf, model=scared.HammingWeight(), discriminant=scared.maxabs, ) att.run(container) last_key = np.argmax(att.scores, axis=0) assert np.array_equal(expected_key, last_key)
def test_snr_on_dpa_v2(): ths = traces.read_ths_from_ets_file('tests/end_to_end/dpa_v2_sub.ets') expected_key = aes.key_schedule(key=ths[0].key)[-1] # SNR with this configuration doesn't retrieve the good value for the first byte of the key. expected_key[0] = 22 sf = aes.selection_functions.encrypt.DeltaRLastRounds() container = scared.Container(ths[:15000]) att = scared.SNRAttack( selection_function=sf, model=scared.HammingWeight(), discriminant=scared.maxabs, ) att.run(container) last_key = np.argmax(att.scores, axis=0) assert np.array_equal(expected_key, last_key)
def test_aes_encrypt_first_round_key_with_default_arguments(): sf = aes.selection_functions.encrypt.FirstAddRoundKey() assert sf.guesses.tolist() == list(range(256)) assert sf.words is Ellipsis assert sf.target_tag == 'plaintext' assert sf.key_tag == 'key' assert isinstance(sf, selection_functions.SelectionFunction) data = np.random.randint(0, 255, (10, 16), dtype='uint8') expected = np.empty((10, 256, 16), dtype='uint8') for i in np.arange(256, dtype='uint8'): expected[:, i, :] = np.bitwise_xor(data, i) assert np.array_equal(expected, sf(plaintext=data)) master_key = np.random.randint(0, 255, (16, ), dtype='uint8') expected_key = aes.key_schedule(master_key)[0] assert np.array_equal(expected_key, sf.compute_expected_key(key=master_key)) assert isinstance(str(sf), str)
def test_aes_encrypt_first_round_key_with_alternative_args(): sf = aes.selection_functions.encrypt.FirstAddRoundKey( plaintext_tag='plain', words=6, guesses=_alt_guesses, key_tag='thekey') assert sf.guesses.tolist() == _alt_guesses.tolist() assert sf.words == 6 assert sf.target_tag == 'plain' assert sf.key_tag == 'thekey' assert isinstance(sf, selection_functions.SelectionFunction) data = np.random.randint(0, 255, (10, 16), dtype='uint8') expected = np.empty((10, len(_alt_guesses), 16), dtype='uint8') for i, guess in enumerate(_alt_guesses): expected[:, i, :] = np.bitwise_xor(data, guess) assert np.array_equal(expected[:, :, 6], sf(plain=data)) master_key = np.random.randint(0, 255, (16, ), dtype='uint8') expected_key = aes.key_schedule(master_key)[0] assert np.array_equal(expected_key, sf.compute_expected_key(thekey=master_key)) assert isinstance(str(sf), str)
def test_key_expansion_bwd_starting_from_any_intermediate_state( key_expansion_params): key = key_expansion_params['key'] cols_size = key_expansion_params['cols_size'] rounds = range(key_expansion_params['rounds'].stop - 1, key_expansion_params['rounds'].start - 1, -1) full_schedule = aes.key_schedule(key).reshape((-1, 4)) _in = len(full_schedule) - cols_size key_base = full_schedule[_in:].reshape((cols_size * 4, )) for intermediate_round in rounds: _out = _in - intermediate_round * 4 schedule_part_1 = aes.key_expansion(key_base, col_in=_in, col_out=_out).reshape((-1, 4)) assert np.array_equal(schedule_part_1, full_schedule[_out:]) sched_part_2 = aes.key_expansion( schedule_part_1[:cols_size].reshape(-1), col_in=_out, col_out=0).reshape((-1, 4)) expected = full_schedule[:_out + cols_size] for i, v in enumerate(sched_part_2): assert np.array_equal(v, expected[i])
def test_aes_decrypt_delta_r_first_rounds_with_default_arguments(): sf = aes.selection_functions.decrypt.DeltaRFirstRounds() assert sf.guesses.tolist() == list(range(256)) assert sf.words is Ellipsis assert sf.target_tag == 'ciphertext' assert isinstance(sf, selection_functions.SelectionFunction) data = np.random.randint(0, 255, (10, 16), dtype='uint8') expected = np.empty((10, 256, 16), dtype='uint8') for i in np.arange(256, dtype='uint8'): expected[:, i, :] = np.bitwise_xor(data, i) s = aes.inv_sub_bytes(state=expected) expected = np.bitwise_xor(aes.shift_rows(data), s.swapaxes(0, 1)).swapaxes(0, 1) assert np.array_equal(expected, sf(ciphertext=data)) master_key = np.random.randint(0, 255, (16, ), dtype='uint8') expected_key = aes.key_schedule(master_key)[-1] assert np.array_equal(expected_key, sf.compute_expected_key(key=master_key)) assert sf.key_tag == 'key' assert isinstance(str(sf), str)
def test_key_expansion_fwd_starting_from_any_intermediate_state( key_expansion_params): key = key_expansion_params['key'] rounds = key_expansion_params['rounds'] cols_size = key_expansion_params['cols_size'] full_schedule = aes.key_schedule(key).reshape((-1, 4)) for intermediate_round in rounds: schedule_part_1 = aes.key_expansion( key, col_out=cols_size + intermediate_round * 4).reshape((-1, 4)) assert np.array_equal( schedule_part_1, full_schedule[:cols_size + intermediate_round * 4]) sched_part_2 = aes.key_expansion( schedule_part_1[len(schedule_part_1) - cols_size:].reshape(-1), col_in=intermediate_round * 4, ).reshape((-1, 4)) expected = full_schedule[intermediate_round * 4:] for i, v in enumerate(sched_part_2): assert np.array_equal(v, expected[i])
def test_aes_decrypt_last_sub_bytes_with_alternative_args(): sf = aes.selection_functions.decrypt.LastSubBytes(plaintext_tag='foo', words=slice(2, 8), guesses=_alt_guesses, key_tag='thekey') assert sf.guesses.tolist() == _alt_guesses.tolist() assert sf.words == slice(2, 8, None) assert sf.target_tag == 'foo' assert isinstance(sf, selection_functions.SelectionFunction) data = np.random.randint(0, 255, (10, 16), dtype='uint8') expected = np.empty((10, len(_alt_guesses), 16), dtype='uint8') for i, guess in enumerate(_alt_guesses): expected[:, i, :] = np.bitwise_xor(data, guess) expected = aes.sub_bytes(expected) assert np.array_equal(expected[:, :, slice(2, 8)], sf(foo=data)) master_key = np.random.randint(0, 255, (16, ), dtype='uint8') expected_key = aes.key_schedule(master_key)[0] assert np.array_equal(expected_key, sf.compute_expected_key(thekey=master_key)) assert sf.key_tag == 'thekey' assert isinstance(str(sf), str)
def test_aes_encrypt_delta_r_last_rounds_with_alternative_args(): sf = aes.selection_functions.encrypt.DeltaRLastRounds(ciphertext_tag='foo', words=slice(2, 8), guesses=_alt_guesses, key_tag='thekey') assert sf.guesses.tolist() == _alt_guesses.tolist() assert sf.words == slice(2, 8, None) assert sf.target_tag == 'foo' assert isinstance(sf, selection_functions.SelectionFunction) data = np.random.randint(0, 255, (10, 16), dtype='uint8') expected = np.empty((10, len(_alt_guesses), 16), dtype='uint8') for i, guess in enumerate(_alt_guesses): expected[:, i, :] = np.bitwise_xor(data, guess) s = aes.inv_sub_bytes(state=expected) expected = np.bitwise_xor(aes.shift_rows(data), s.swapaxes(0, 1)).swapaxes(0, 1) assert np.array_equal(expected[:, :, slice(2, 8)], sf(foo=data)) master_key = np.random.randint(0, 255, (16, ), dtype='uint8') expected_key = aes.key_schedule(master_key)[-1] assert np.array_equal(expected_key, sf.compute_expected_key(thekey=master_key)) assert isinstance(str(sf), str)
def test_key_schedule_raise_exception_if_key_hasnt_a_valid_size(): with pytest.raises(ValueError): key = np.random.randint(0, 255, size=(8, )) aes.key_schedule(key=key)
def test_key_schedule_raise_exception_if_key_isnt_int8_array(): with pytest.raises(ValueError): key = np.random.random_sample((16, )) aes.key_schedule(key=key)
def test_inv_key_schedule_with_multiple_keys_returns_appropriate_keys(): master_keys = np.random.randint(0, 255, (10, 16), dtype='uint8') round_keys = aes.key_schedule(master_keys) for i in range(round_keys.shape[1]): res = aes.inv_key_schedule(round_keys[:, i, :], i) assert np.array_equal(round_keys, res)