Читаем Программирование. Принципы и практика использования C++ Исправленное издание полностью

Не следует слишком глубоко вникать в этот код (если вы не слишком любознательны или не хотите заработать головную боль). Мы приводим его просто для того, чтобы вы почувствовали вкус реального приложения и ощутили полезность манипулирования битами. Если хотите изучать вопросы шифрования, найдите другой учебник. Более подробную информацию об этом алгоритме и варианты его реализации на других языках программирования можно найти на веб-странице 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;

Перейти на страницу:

Похожие книги

Programming with POSIX® Threads
Programming with POSIX® Threads

With this practical book, you will attain a solid understanding of threads and will discover how to put this powerful mode of programming to work in real-world applications. The primary advantage of threaded programming is that it enables your applications to accomplish more than one task at the same time by using the number-crunching power of multiprocessor parallelism and by automatically exploiting I/O concurrency in your code, even on a single processor machine. The result: applications that are faster, more responsive to users, and often easier to maintain. Threaded programming is particularly well suited to network programming where it helps alleviate the bottleneck of slow network I/O. This book offers an in-depth description of the IEEE operating system interface standard, POSIX (Portable Operating System Interface) threads, commonly called Pthreads. Written for experienced C programmers, but assuming no previous knowledge of threads, the book explains basic concepts such as asynchronous programming, the lifecycle of a thread, and synchronization. You then move to more advanced topics such as attributes objects, thread-specific data, and realtime scheduling. An entire chapter is devoted to "real code," with a look at barriers, read/write locks, the work queue manager, and how to utilize existing libraries. In addition, the book tackles one of the thorniest problems faced by thread programmers-debugging-with valuable suggestions on how to avoid code errors and performance problems from the outset. Numerous annotated examples are used to illustrate real-world concepts. A Pthreads mini-reference and a look at future standardization are also included.

David Butenhof

Программирование, программы, базы данных