132 lines
2.8 KiB
C++
132 lines
2.8 KiB
C++
#include <iostream>
|
|
#include <fstream>
|
|
#include <set>
|
|
#include <algorithm>
|
|
|
|
#include "types.hpp"
|
|
#include "aes.hpp"
|
|
|
|
const int no_traces = 10'000;
|
|
|
|
using namespace std;
|
|
|
|
char read_char(istream &stream)
|
|
{
|
|
char buf;
|
|
stream.get(buf);
|
|
return buf;
|
|
}
|
|
|
|
traces_vector_t load_traces()
|
|
{
|
|
traces_vector_t traces(no_traces, trace());
|
|
//ifstream plaintexts("plaintexts.dat", ios::binary);
|
|
ifstream ciphertexts("ciphertexts.dat", ios::binary);
|
|
ifstream faultytexts("faultytexts.dat", ios::binary);
|
|
for (int trace_no = 0;trace_no < no_traces;trace_no++)
|
|
{
|
|
trace ¤t_trace = traces[trace_no];
|
|
for (int i = 0;i < 16;i++)
|
|
{
|
|
//current_trace.plaintext[i] = read_char(plaintexts);
|
|
current_trace.ciphertext[i] = read_char(ciphertexts);
|
|
current_trace.faultytext[i] = read_char(faultytexts);
|
|
}
|
|
}
|
|
if (!ciphertexts.good() || !ciphertexts.good())
|
|
{
|
|
cout << "IO ERROR";
|
|
exit(1);
|
|
}
|
|
return traces;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
const int faultpos = 1;
|
|
traces_vector_t traces = load_traces();
|
|
aes_col_vector_t deltas = aes_col_vector_t(256, aes_col());
|
|
for (int i = 0;i < 256;i++)
|
|
{
|
|
deltas[i].column[faultpos] = i;
|
|
AES::mix_column(deltas[i].column);
|
|
}
|
|
|
|
aes_col key;
|
|
set<aes_col> candidates;
|
|
for (int i = 0;i < no_traces;i++)
|
|
{
|
|
cout << i;
|
|
cout.flush();
|
|
set<aes_col> round_candidates;
|
|
for (int k0 = 0;k0 < 256;k0++)
|
|
{
|
|
for (int k1 = 0;k1 < 256;k1++)
|
|
{
|
|
for (int k2 = 0;k2 < 256;k2++)
|
|
{
|
|
for (int k3 = 0;k3 < 256;k3++)
|
|
{
|
|
key.column[0] = k0;
|
|
key.column[1] = k1;
|
|
key.column[2] = k2;
|
|
key.column[3] = k3;
|
|
aes_col diff;
|
|
trace current = traces[i];
|
|
AES::shift_rows(current.ciphertext);
|
|
AES::shift_rows(current.faultytext);
|
|
for (int j = 0;j < 4;j++)
|
|
{
|
|
current.ciphertext[j] = AES::inv_sbox[current.ciphertext[j] ^ key.column[j]];
|
|
current.faultytext[j] = AES::inv_sbox[current.faultytext[j] ^ key.column[j]];
|
|
diff.column[j] = current.ciphertext[j] ^ current.faultytext[j];
|
|
}
|
|
for (int delta = 0;delta < 256;delta++)
|
|
{
|
|
if (diff == deltas[delta])
|
|
{
|
|
round_candidates.insert(key);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (i == 0)
|
|
{
|
|
candidates = round_candidates;
|
|
}
|
|
else
|
|
{
|
|
set<aes_col> intersection;
|
|
set_intersection(candidates.begin(), candidates.end(), round_candidates.begin(), round_candidates.end(), std::inserter(intersection, intersection.begin()));
|
|
candidates = intersection;
|
|
}
|
|
|
|
if (candidates.size() == 1)
|
|
{
|
|
cout << endl;
|
|
break;
|
|
}
|
|
else if (candidates.size() == 0)
|
|
{
|
|
cout << endl << "Error!" << endl;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
cout << " -> " << candidates.size() << endl;
|
|
}
|
|
}
|
|
|
|
cout << "Key: ";
|
|
key = *candidates.begin();
|
|
for (int i = 0; i < 4;i++)
|
|
{
|
|
cout << key.column[i] << " ";
|
|
}
|
|
cout << endl;
|
|
return 0;
|
|
}
|