Міністерство освіти і науки України
Національний університет „Львівська політехніка”
Кафедра електронних
обчислювальних машин
Звіт
про виконання лабораторної роботи № 5
з курсу „ Захист інформації в комп’ютерних системах ”
Метод стовпцевих перестановок
Львів – 2005
Мета роботи: ознайомитися із методом стовпцевих перестановок та закріпити навики  кодування тексту за допомогою цього методу.
Завдання: За допомогою алгоритму стовпцевих перестановок закодувати вхідний текст.
Текст програми:
// Max_ZI5.cpp
#include "stdafx.h"
#include "stdlib.h"
#include "io.h"
#include "math.h"
void error();
void encrypt(char*,char*);
void decrypt(char*,char*);
#define max_rows 20
#define max_columns 20
int main(int argc, char* argv[])
{
  char mode;
  puts("Stovptsevi peretvotennia. Lab 5 ZI\n *** (C) m@Qs, ki44 2005 ***\n");
  if (argc!=4) error();
  mode=argv[1][0];
  if ( mode=='e') encrypt(argv[2],argv[3]);
  else if ( mode=='d') decrypt(argv[2],argv[3]);
      else {
        error();
      }
  puts("\nDONE!");  return 0;
}
void encrypt(char* in,char* out) //into bmp
{
  FILE * f_in;   // вказівник на вхідний файл
  FILE * f_out;  // вказівник на файл з зашифрованим текстом
  char ch;   // символьна змінна для збереження зчитаних з вхідного файлу символів
  int txt_length=0;     // довжина тексту для шифрування
  int array_rows=0;     // кількість зайнятих рядків в масиві
  int array_columns=0;  // кількість зайнятих стовпців в масиві
  int tmp;              // змінна для проміжних результатів обчислень
  int i,j;
  char buf[max_rows][max_rows]; // масив, з допомогою якого здійснюється шифрування
  // Відкриваємо вхідний та вихідний файли
  if((f_in=fopen(in,"r")) == NULL)
    { printf("Unable to open input file %c\n",in);   exit(1); }
  if((f_out=fopen(out,"w")) == NULL)
    { printf("Unable to open output file %c\n",out); exit(1); }
  // Визначаємо довжину тексту, який необхідно зашифрувати
  fscanf(f_in,"%c",&ch);
  while(!feof(f_in))
  {
    if ( (ch != ' ') && (ch != '\n'))    // Пробіли і \n не враховуємо
      txt_length++;
    fscanf(f_in,"%c",&ch);    
  }
  // Довжина тексту не перевищує максимальної?
  if (txt_length > 400)
  {
    printf("Text to encode is too long.");   exit(1);
  }
  // Знову відкриваємо вхідний файл для читання спочатку
  fclose(f_in);
  f_in=fopen("text.txt", "r");
  // Визначення кількості рядків і стовпців масиву, які будуть зайняті текстом
  array_rows = sqrt(txt_length);
  array_columns = array_rows;
  tmp = txt_length - array_rows*array_rows;
  if ( tmp >= array_rows)
  {
    array_rows++;
    array_columns++;
  }
  else if( tmp>0)
    array_columns++;  
  // Початкове обнулення масиву
  for (i=0; i<max_rows; i++)  for (j=0; j<max_columns; j++)  buf[i][j]=0;
  // Запис даних з файлу в масив порядково
  fscanf(f_in,"%c",&ch);
  for (i=0; i<=array_rows-1; i++)
  {
    for (j=0; j<=array_columns-1; j++)
    {
      while ( (ch == ' ') || (ch == '\n'))     // пробіли і \n не враховуємо
        if (!feof(f_in))      // читаємо з файлу символи доки не друкований символ
          fscanf(f_in,"%c",&ch);    // та записуємо його в змінну ch      
      if (!feof(f_in))        // записуємо вміст ch в відповідну комірку масиву
      { buf[i][j]=ch; fscanf(f_in,"%c",&ch); }
    }    
  }  
  // Вивід масиву по стовпцях в вихідний файл
  for (i=0; i<=array_rows-1; i++)  {
    for (j=0; j<=array_columns-1; j++)  fprintf(f_out,"%c",buf[j][i]);
    fprintf(f_out," ");
  }  
  printf("Everething mixed up ;) Results in %c\n",out);
  fclose(f_in);// закриваємо усі відкриті файли
  fclose(f_out);  
}
void decrypt(char* in,char* out) //from bmp
{
  FILE * f_in;   // вказівник на вхідний файл
  FILE * f_out;  // вказівник на файл з зашифрованим текстом
  char ch;   // символьна змінна для збереження зчитаних з вхідного файлу символів  
  int i,j;
  char buf[max_rows][max_rows];  // масив, з допомогою якого здійснюється шифрування тексту
  // Відкриваємо вхідний та вихідний файли
  if((f_in=fopen(in,"r")) == NULL)
  {
    printf("Unable to open input file %c\n",in);
    exit(1);
  }
  if((f_out=fopen(out,"w")) == NULL)
  {
    printf("Unable to open output file %c\n",out);
    exit(1);
  }
  // Початкове обнулення масиву
  for (i=0; i<max_rows; i++)
    for (j=0; j<max_columns; j++)  buf[i][j]=0;
  // Запис даних з файлу в масив по стовпчикам
  fscanf(f_in,"%c",&ch);
  for (i=0; i<max_rows; i++)
  {
    for (j=0; j<max_columns; j++)
    {
      if ((ch != ' ') && (ch != '\n') && (ch != 0))
      {
        if (!feof(f_in)) // записуємо вміст ch в відповідну комірку масиву
        { buf[j][i]=ch; fscanf(f_in,"%c",&ch); }
      }
      else { fscanf(f_in,"%c",&ch); break; }
    }    
  }  
  // Вивід масиву по рядках в вихідний файл
  for (i=0; i<max_rows; i++)
    for (j=0; j<max_columns; j++)
      if(buf[i][j] != 0)
        fprintf(f_out,"%c",buf[i][j]);
  printf("Finished. See decripted text in %c\n",out);
  fclose(f_in);// закриваємо усі відкриті файли
  fclose(f_out);  
}
void error()
{
  puts("Wrong parameters!\nSYNTAX: maxZI5_full e|d <input file> <output file>");
  getchar();  exit(-1);
} 
Результати виконання програми:
Вхідний текст:					Laboratorna robota n.5 z ZI
Зашифрований текст:				LaatzatraZboonIorb. rno5  
Розшифрований (відновлений) текст:		Laboratornarobotan.5zZI
	
Як бачимо, вхідний текст повністю відновлен за виключенням пробілів між словами. 
Висновок: виконуючи цю лабораторну роботу, я навчився створювати хеш для будь-якої вхідної послідовності за допомогою алгоритму хешування MD5.