Commit 767fe721927d1175e22e14651be9f240a0ca1d3d

Authored by Brice Colombier
1 parent 856f31af5c
Exists in master

Deleted shifted CPA

Showing 1 changed file with 0 additions and 211 deletions

shifted_1st_order_CPA.py View file @ 767fe72
1   -# coding: utf8
2   -
3   -import numpy as np
4   -from scipy.stats.stats import pearsonr
5   -import matplotlib.pyplot as plt
6   -import matplotlib.ticker as ticker
7   -import logging as log
8   -import scipy.io as sio
9   -from random import randint
10   -
11   -import argparse
12   -import sys
13   -sys.path.append('./../Correlation')
14   -import corr as corr
15   -
16   -import os
17   -
18   -log.basicConfig(format="%(levelname)s: %(message)s", level=log.INFO)
19   -
20   -# Hamming weight rray
21   -HW_array = np.array([str(bin(byte)[2:]).count('1') for byte in range(256)], dtype=np.uint8)
22   -
23   -nb_bytes = 16
24   -nb_k_hyp = 256
25   -
26   -Sbox_hex = [
27   - 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
28   - 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
29   - 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
30   - 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
31   - 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
32   - 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
33   - 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
34   - 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
35   - 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
36   - 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
37   - 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
38   - 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
39   - 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
40   - 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
41   - 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
42   - 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16]
43   -
44   -Sbox_dec = np.array([int(s) for s in Sbox_hex])
45   -
46   -inv_Sbox_hex = [
47   - 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
48   - 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
49   - 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
50   - 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
51   - 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
52   - 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
53   - 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
54   - 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
55   - 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
56   - 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
57   - 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
58   - 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
59   - 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
60   - 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
61   - 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
62   - 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D]
63   -
64   -inv_Sbox_dec = np.array([int(s) for s in inv_Sbox_hex])
65   -
66   -def compute_predictions(leakage_model,
67   - attacked_round,
68   - nb_traces,
69   - plaintexts_path = './plaintexts',
70   - ciphertexts_path = './ciphertexts',
71   - predictions_path = './predictions',
72   - save_mat = False):
73   - k_hyps = np.array(range(nb_k_hyp)) #0 to 255
74   - shift = randint(0, nb_traces)
75   - if attacked_round.lower() == 'first':
76   - for plaintexts_filename in os.listdir(plaintexts_path):
77   - plaintexts = np.load(os.path.join(plaintexts_path, plaintexts_filename))
78   - plaintexts = np.vstack((plaintexts[shift:], plaintexts[:shift]))
79   - plaintexts = plaintexts[:nb_traces,:]
80   - break
81   - # Compute the reference value against which the Hamming distance is computed
82   - if leakage_model.lower() =='hamming_weight':
83   - ref_value = np.zeros((np.shape(plaintexts)[0], np.shape(plaintexts)[1], nb_k_hyp)).astype(np.uint8)
84   - elif leakage_model.lower() == 'hamming_distance_plaintext':
85   - ref_value = plaintexts[:, :, np.newaxis]
86   - elif leakage_model.lower() == 'hamming_distance_sbox_input':
87   - ref_value = np.bitwise_xor(plaintexts[:, :, np.newaxis], k_hyps)
88   - predictions = HW_array[np.bitwise_xor(Sbox_dec[np.bitwise_xor(plaintexts[:, :, np.newaxis], k_hyps)], ref_value)]
89   - elif attacked_round.lower() == 'last':
90   - for ciphertexts_filename in os.listdir(ciphertexts_path):
91   - ciphertexts = np.load(os.path.join(ciphertexts_path, ciphertexts_filename))
92   - break
93   - if leakage_model.lower() =='hamming_weight':
94   - ref_value = np.zeros((np.shape(ciphertexts)[0], np.shape(ciphertexts)[1], nb_k_hyp)).astype(np.uint8)
95   - ref_value = ref_value[:, :, np.newaxis]
96   - predictions = HW_array[np.bitwise_xor(inv_Sbox_dec[np.bitwise_xor(ciphertexts[:, :, np.newaxis], k_hyps)], ref_value)]
97   - np.save(os.path.join(predictions_path, 'prediction.npy'), predictions)
98   - if save_mat:
99   - sio.savemat(os.path.join(predictions_path, 'prediction.mat'), {'prediction':predictions.astype(np.float32)})
100   - log.info("Predictions for intermediate value in {0} round computed".format(attacked_round))
101   - return shift
102   -
103   -def compute_correlation(nb_traces,
104   - shift=0,
105   - predictions_path = './predictions',
106   - traces_path = './traces',
107   - correlations_path = './correlations'):
108   - for predictions_filename in os.listdir(predictions_path):
109   - predictions = np.load(os.path.join(predictions_path, predictions_filename))
110   - break
111   - log.info("Loaded predictions matrix of type {0} and size {1}".format(predictions.dtype, np.shape(predictions)))
112   - for traces_filename in os.listdir(traces_path):
113   - traces = np.load(os.path.join(traces_path, traces_filename))
114   - traces = np.vstack((traces[shift:], traces[:shift]))
115   - traces = traces[:nb_traces,:]
116   - break
117   - log.info("Loaded traces ("+traces_filename+") matrix of type {0} and size {1}".format(traces.dtype, np.shape(traces)))
118   - nb_samples = np.shape(traces)[1]
119   - correlation = np.zeros((nb_bytes, nb_samples, nb_k_hyp))
120   - for byte in range(nb_bytes):
121   - log.info("Computing correlation for byte {0}".format(byte))
122   - correlation[byte,:,:] = corr.corr(traces, predictions[:,byte,:])
123   - np.save(os.path.join(correlations_path, 'corr_byte_'+str(byte)+'.npy'), correlation[byte,:,:])
124   -
125   -def display_results(correct_key,
126   - attacked_round = 'first',
127   - correlations_path = './correlations'):
128   - correct_key = [correct_key[i:i+2] for i in range(0, len(correct_key), 2)]
129   - guessed_key = ""
130   - for byte, correct_byte in enumerate(correct_key):
131   - corr = np.load(os.path.join(correlations_path, 'corr_byte_'+str(byte)+'.npy'))
132   - max_corr_per_key_byte = abs(corr).max(axis=0)
133   - max_corr_samples = abs(corr).max(axis=1)
134   - hex_key_byte = hex(np.argmax(max_corr_per_key_byte))[2:-1].zfill(2)
135   - sample_of_interest = np.argmax(max_corr_samples)
136   - corr = round(max(max_corr_per_key_byte), 3)
137   - if attacked_round.lower() == 'first':
138   - log.info("=> Guessed key byte #{0} : \"{1}\", found at sample {2}".format(str(byte).zfill(2), hex_key_byte, sample_of_interest))
139   - position_correct_byte = list(np.sort(max_corr_per_key_byte)[::-1]).index(max_corr_per_key_byte[int(correct_byte, 16)])
140   - log.info(" => Correct one is \"{0}\", ranked {1}/{2} with correlation={3}".format(correct_byte, position_correct_byte, nb_k_hyp, corr))
141   - guessed_key+=hex_key_byte
142   - elif attacked_round.lower() == 'last':
143   - log.info("=> Guessed last round key byte #{0} : \"{1}\", found at sample {2}".format(str(byte).zfill(2), hex_key_byte, sample_of_interest))
144   - position_correct_byte = list(np.sort(max_corr_per_key_byte)[::-1]).index(max_corr_per_key_byte[int(correct_byte, 16)])
145   - log.info(" => Correct one is \"{0}\", ranked {1}/{2} with correlation={3}".format(correct_byte, position_correct_byte, nb_k_hyp, corr))
146   - guessed_key+=hex_key_byte
147   - if attacked_round.lower() =='first':
148   - print "=> Guessed key is \"{0}\"".format(guessed_key)
149   - elif attacked_round.lower() =='last':
150   - print "=> Guessed last round key is \"{0}\"".format(guessed_key)
151   -
152   -def plot_results(target_bytes,
153   - correlations_path = './correlations',
154   - plot_path="./plots"):
155   - for byte in target_bytes:
156   - log.info("Plotting for byte {0}".format(byte))
157   - corr = abs(np.load(os.path.join(correlations_path, 'corr_byte_'+str(byte)+'.npy')))
158   - nb_samples, nb_hyp = np.shape(corr)
159   - max_corr_per_key_byte = abs(corr).max(axis=0)
160   - max_corr_samples = abs(corr).max(axis=1)
161   - key_byte = np.argmax(max_corr_per_key_byte)
162   - hex_key_byte = hex(key_byte)[2:-1].zfill(2)
163   - sample_of_interest = np.argmax(max_corr_samples)
164   - plt.figure()
165   - plt.plot(corr[:,:key_byte], color = 'grey', linewidth = 0, marker="o", markersize=4)
166   - plt.plot(corr[:,-key_byte:], color = 'grey', linewidth = 0, marker="o", markersize=4)
167   - plt.plot(corr[:,key_byte], color = 'blue', linewidth = 0, marker="o", markersize=4)
168   - plt.xlim(0,nb_samples)
169   - plt.ylim(0, 1)
170   - plt.xlabel("Echantillons (temps)")
171   - plt.ylabel("Correlation")
172   - # plt.savefig(os.path.join(plot_path, 'corr_vs_samples_byte_'+str(byte)+'.png'))
173   - # plt.show()
174   - plt.figure()
175   - plt.plot(corr.transpose(), color = 'grey', linewidth = 0, marker="o", markersize=4)
176   - plt.plot(nb_samples*[key_byte], corr[:,key_byte], color = 'red', linewidth = 0, marker="o", markersize=4)
177   - plt.xlim(-1,nb_hyp-1)
178   - axes = plt.gca()
179   - axes.get_xaxis().set_major_locator(ticker.MultipleLocator(16))
180   - axes.get_xaxis().set_major_formatter(ticker.FormatStrFormatter("%x"))
181   - plt.ylim(0, 1)
182   - plt.xlabel("Hypotheses de cle")
183   - plt.ylabel("Correlation")
184   - plt.show()
185   - # plt.savefig(os.path.join(plot_path, 'corr_vs_k_hyp_byte_'+str(byte)+'.png'))
186   -
187   -if __name__ == "__main__":
188   -
189   - parser = argparse.ArgumentParser(description='Preprocess traces')
190   - parser.add_argument("nb_traces", type=int)
191   - args = parser.parse_args()
192   - nb_traces = args.nb_traces
193   - compute_predictions(leakage_model = 'hamming_weight', attacked_round = 'first', nb_traces = nb_traces)
194   - compute_correlation(nb_traces = nb_traces)
195   - display_results(correct_key = '0123456789abcdef123456789abcdef0')
196   - # for i in range(1):
197   - # shift = compute_predictions(leakage_model = 'hamming_weight', attacked_round = 'first', nb_traces = nb_traces)
198   - # compute_correlation(nb_traces = nb_traces, shift = shift)
199   - # display_results(correct_key = "0123456789abcdef123456789abcdef0")
200   - # display_results(correct_key = '4dfbe0f27221fe10a78d4adc8e490469')
201   - # plot_results(range(15))
202   - # compute_predictions(leakage_model = 'hamming_distance_plaintext', attacked_round = 'first')
203   - # compute_correlation()
204   - # display_results(correct_key = '0123456789abcdef123456789abcdef0')
205   - # compute_predictions(leakage_model = 'hamming_distance_sbox_input', attacked_round = 'first')
206   - # compute_correlation()
207   - # display_results(correct_key = '0123456789abcdef123456789abcdef0')
208   - # plot_results()
209   - # compute_predictions(attacked_round = 'last')
210   - # compute_correlation()
211   - # display_results(correct_key = '0123456789abcdef123456789abcdef0')