Program: napisać w języku ANSI C kod źródłowy programu wykorzystującego szyfr afiniczny z 256-elementowym alfabetem.
Wraz z parametrami wywołania jak w ostatnim przykładzie. Ilość elementów w alfabecie (zakres bajtu: 0-255) daje możliwość wykorzystania programu do szyfrowania plików binarnych.
Zaimplementować w programie wraz z prostym interfejsem (np. opcje wiersza poleceń) szyfrowanie plików binarnych. Sprawdzić poprawne działanie programu wykorzystując np. obrazki, pliki audio, video, ogólnie multimedia.
Film:
Kod programu:
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
unsigned n= 256;
unsigned nwd(unsigned, unsigned, int *, int *);
int main(int argc, char *argv[])
{
int a, b, x, y, koniec = 0;
unsigned d;
do{
int akcja = 0;
fprintf(stderr, "\nJaka akcje chcesz wykonac:\n1. Szyfrowanie\n2. Deszyfrowanie\n3. Wyjdz z programu\n\n");
scanf("%d", &akcja);
if (akcja == 1 || akcja == 2)
{
int liczba = 0;
printf ("Podaj pierwsza liczbe (musi byc ona nieparzysta): ");
scanf ("%d", &liczba);
int liczba2 = 0;
printf ("Podaj druga liczbe: ");
scanf ("%d", &liczba2);
a = liczba;
if (a < 0)
a = n - (-a) % n;
else
a %= n;
b = liczba2;
if (b < 0)
b = n - (-b) % n;
else
b %= n;
d = nwd(a, n, &x, &y);
if (d != 1) {
fprintf(stderr, "BLAD: a=%u w kluczu (%u, %u) jest NIEODWRACALNE modulo 256.\n\n", a, a, b);
return 2;
}
if( argc > 1 )
listujPliki( argv[ 1 ] );
else
listujPliki( "." );
}
if (akcja == 2) {
int a0 = a, b0 = b;
a = x > 0 ? x % n : (n - (-x) % n);
b *= -a;
b = b >= 0 ? b % n : (n - (-b) % n);
fprintf(stderr,
"Przeksztalcenie kluczy (%u, %u) => (%u, %u) mod 256\n Deszyfrowanie kluczem tajnym-odwrotnym: (%u, %u) mod 256:\nPodaj nazwe pliku jaki deszyfowac:\n",
a0, b0, a, b,
a, b);
} else if(akcja == 1)
fprintf(stderr, "Szyfrowanie kluczem tajnym: (%u, %u) mod 256:\nPodaj nazwe pliku w folderze projektu:\n", a, b);
else{
fprintf(stderr, "Wylaczam program!");
}
if (akcja == 2) {
char xa;
char deszyfowany_plik[100];
scanf("%100s", deszyfowany_plik);
FILE *fi_o = fopen(deszyfowany_plik, "rb");
if (fi_o == NULL)
{
printf("Plik do deszyfrowania nie istnieje");
exit(-1);
}
fprintf(stderr, "Podaj nazwe pliku docelowego:\n");
char plik_docelowy[100];
scanf("%100s", plik_docelowy);
FILE *fi = fopen(plik_docelowy, "wb");
int znak;
znak = getc( fi_o );
while( znak != EOF )
{
if (0 <= znak && znak <= 255){
xa = (0 + (a * (znak - 0) + b) % n);
printf( "%c", xa );
fprintf(fi, "%c", xa);
znak = getc( fi_o );
}
else
putchar(znak);
}
fclose(fi);
fclose(fi_o);
}
else if(akcja == 1){
char xa;
char plik_szyfrowany[100];
scanf("%100s", plik_szyfrowany);
FILE *fi_o = fopen(plik_szyfrowany, "rb");
if (fi_o == NULL)
{
printf("Plik do zaszyfrowania nie istnieje");
exit(-1);
}
fprintf(stderr, "Podaj nazwe pliku do jakiego zaszyfrowac:\n");
char plik_docelowy[100];
scanf("%100s", plik_docelowy);
FILE *fi = fopen(plik_docelowy, "wb");
int znak;
znak = getc( fi_o );
while( znak != EOF )
{
if (0 <= znak && znak <= 255){
xa = (0 + (a * (znak - 0) + b) % n);
printf( "%c", xa );
fprintf(fi, "%c", xa);
znak = getc( fi_o );
}
else
putchar(znak);
}
fclose(fi);
fclose(fi_o);
}
else
{
return 1;
}
}while(koniec != 1);
return 0;
}
unsigned nwd(unsigned a, unsigned b, int *x, int *y)
{
if (b == 0) {
*x = 1;
*y = 0;
return a;
} else {
unsigned d;
int x1, y1;
d = nwd(b, a % b, &x1, &y1);
*x = y1;
*y = x1 - y1 * (a / b);
return d;
}
}
void listujPliki( const char * nazwa_sciezki ) {
struct dirent * plik;
DIR * sciezka;
if(( sciezka = opendir( nazwa_sciezki ) ) ) {
while(( plik = readdir( sciezka ) ) )
puts( plik->d_name );
closedir( sciezka );
}
else
printf( "! Wywołując funkcję opendir(%s) pojawił się błąd otwarcia strumienia dla danej ścieżki, może nie istnieje, lub podano ścieżkę pustą\n", nazwa_sciezki );
}
Słowniczek pojęć:
Jest to szyfr podstawieniowy co oznacza, że jednej literze tekstu jawnego odpowiada jedna litera alfabetu tajnego. Podczas szyfrowania tą metodą kluczem jest para liczb naturalnych (a, b). Wtedy szyfrowana litera l jest wyliczana z funkcji f(l) = al + b mod m. Litera m we wzorze oznacza liczbę liter w alfabecie. W przypadku alfabetu angielskiego m = 26, a w przypadku polskiego m = 32.