Не следует слишком глубоко вникать в этот код (если вы не слишком любознательны или не хотите заработать головную боль). Мы приводим его просто для того, чтобы вы почувствовали вкус реального приложения и ощутили полезность манипулирования битами. Если хотите изучать вопросы шифрования, найдите другой учебник. Более подробную информацию об этом алгоритме и варианты его реализации на других языках программирования можно найти на веб-странице http://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm или на сайте, посвященному алгоритму TEA и созданному профессором Саймоном Шепердом (Simon Shepherd) из Университета Брэдфорда (Bradford University), Англия. Этот код не является самоочевидным (без комментариев!).
Основная идея шифрования/дешифрования (кодирования/декодирования) проста. Я хочу послать вам некий текст, но не хочу, чтобы его прочитал кто-то другой. Поэтому я преобразовываю свой текст так, чтобы он стал непонятным для людей, которые не знают, как именно я его модифицировал, но так, чтобы вы могли произвести обратное преобразование и прочитать мой текст. Эта процедура называется шифрованием. Для того чтобы зашифровать текст, я использую алгоритм (который должен считать неизвестным нежелательным соглядатаям) и строку, которая называется ключом. У вас этот ключ есть (и надеемся, что его нет у нежелательного соглядатая). Когда вы получите зашифрованный текст, вы расшифруете его с помощью ключа; другими словами, восстановите исходный текст, который я вам послал.
Алгоритм TEA получает в качестве аргумента два числа типа long
без знака (v[0]
, v[1]
), представляющие собой восемь символов, которые должны быть зашифрованы; массив, состоящий из двух чисел типа long
без знака (w[0]
, w[1]
), в который будет записан результат шифрования; а также массив из четырех чисел типа long
без знака (k[0]..k[3]
), который является ключом.
void encipher(
const unsigned long *const v,
unsigned long *const w,
const unsigned long * const k)
{
unsigned long y = v[0];
unsigned long z = v[1];
unsigned long sum = 0;
unsigned long delta = 0x9E3779B9;
unsigned long n = 32;
while(n–– > 0) {
y += (z << 4 ^ z >> 5) + z ^ sum + k[sum&3];
sum += delta;
z += (y << 4 ^ y >> 5) + y ^ sum + k[sum>>11 & 3];
}
w[0]=y; w[1]=z;
}
}
Поскольку все данные не имеют знака, мы можем выполнять побитовые операции, не опасаясь сюрпризов, связанных с отрицательными числами. Основные вычисления выполняются с помощью сдвигов (<<
и >>
), исключительного “или” (^
) и побитовой операции “и” (&
) наряду с обычным сложением (без знака). Этот код написан специально для машины, в которой тип long занимает четыре байта. Код замусорен “магическими” константами (например, он предполагает, что значение sizeof(long)
равно 4
). Обычно так поступать не рекомендуется, но в данном конкретном коде все это ограничено одной страницей, которую программист с хорошей памятью должен запомнить как математическую формулу. Дэвид Уиллер хотел шифровать свои тексты, путешествуя без ноутбуков и других устройств. Программа кодирования и декодирования должна быть не только маленькой, но и быстрой. Переменная n
определяет количество итераций: чем больше количество итераций, тем сильнее шифр. Насколько нам известно, при условии n==32
алгоритм TEA никогда не был взломан.
Приведем соответствующую функцию декодирования.
void decipher(
const unsigned long *const v,
unsigned long *const w,
const unsigned long * const k)
{
unsigned long y = v[0];
unsigned long z = v[1];
unsigned long sum = 0xC6EF3720;
unsigned long delta = 0x9E3779B9;
unsigned long n = 32;
// sum = delta<<5, в целом sum = delta * n
while(n–– > 0) {
z –= (y << 4 ^ y >> 5) + y ^ sum + k[sum>>11 & 3];
sum –= delta;
y –= (z << 4 ^ z >> 5) + z ^ sum + k[sum&3];
}
w[0]=y; w[1]=z;
}
}
Мы можем использовать алгоритм TEA для того, чтобы создать файл, который можно передавать по незащищенной линии связи.
int main() // отправитель
{
const int nchar = 2*sizeof(long); // 64 бита
const int kchar = 2*nchar; // 128 битов
string op;
string key;
string infile;
string outfile;