Szyfrowanie afiniczne.

0

Witam.

Mam program szyfrujący afinicznie wpisany tekst. Chciałbym go przerobić tak by wczytywał plik bajt po bajcie a następnie po wpisaniu dwóch kluczy kodowal go i zapisywał do pliku oraz by mógł dekodować wcześniej zakodowany plik.
Bardzo proszę o radę jak go przerobić i czy w ogóle da się to zrobić.

Proszę również o brak chamskich komentarzy. Dopiero się uczę dlatego pytam bardziej doświadczonych ludzi ode mnie, którym bardzo dziękuję za przejaw jakiejkolwiek pomocy.

#include<string.h>
#include<iostream.h>
void encode(int a, int b);
void uncode(int a, int b);
int getUncode(int a);

int main()
{
	int a, b,c,d;
	cout<<"Wprowadź klucze kodowania K(A,B)"<<endl;
	cin>>a>>b;
	c = getUncode(a);
	d = -b;
    cout<<"Twój klucz to K("<<c<<","<<d<<")"<<endl;
	encode(a,b);
	uncode(c,d);
	return 0;
}


void encode(int a,int b)
{
    int  len=0,i=0,j=0,temp;
    char s[1000];
	char s1[1000];
	
	cout<<"Wprowadź tekst do zakodowania"<<endl;
	cout<<"(Uwaga! Wymagane małe litery i maksymalnie 1000 znaków.)"<<endl;
    cin>>s;
	len = strlen(s);
    for(i = 0,j = 0;i<len;i++)
	{   
		temp = (a*(s[i]-97)+b)%26;
		if(temp<0) temp += 26; 
		s1[i]= temp +97;
	}
	s1[i]='\0';
	cout<<"Zakodowany ciąg znaków:"<<endl;
	cout<<s1<<endl;
}

void uncode(int a,int b)
{
	int  len=0,i=0,j=0;
    char s[1000];
	char s1[1000];
	cout<<"Wprowadź tekst"<<endl;
	cout<<"(Uwaga! Wymagane małe litery i maksymalnie 1000 znaków.)"<<endl;
    cin>>s;
	len = strlen(s);
    for(i = 0,j = 0;i<len;i++)
		s1[i]=(a*(s[i]-97)+b)%26+97;
	s1[i]='\0';
	cout<<"Zakodowany ciąg znaków:"<<endl;
	cout<<s1<<endl;
}

int getUncode(int a)
{
   int i,b;
   for(i = 1; i<a;i++)
   {
     b = ( 26*i + 1 )/a;
     if(( 26*i + 1 )%a==0)
		 return b;
		 SYSTEM("PAUSE");
   }
}
0

Co do samego użycia szyfrowania afinicznego do plików binarnych, to ja nie widzę przeciwwskazań.
Oczywiście musiałbyś wziąć pod uwagę fakt, że operujesz wtedy na 256 różnych wartościach, i dokładnie pod tym kątem zmodyfikować funkcje szyfrujące/deszyfrujace.
Implementację zapisu/odczytu z plików wykonasz fstream'em obecnym w standardzie.

Ponadto:

#include<cstring>
#include<iostream>
using namespace std;

zamiast

#include<string.h>
#include<iostream.h>

A do zatrzymywania konsoli, jeśli już musimy to zrobić, to zamiast system("pause") powinno się używać

cin.ignore().get();
0

krok pierwszy to zrozumienie jak działa szyfr afiniczny i jakie są jego ograniczenia!
Brakuje ci sprawdzenia czy klucz jest prawidłowy! Patrz wiki! U ciebie m=26 co nie jest liczbą pierwszą, masz więc ryzyko, że NWD(a,m) nie będzie równe zero: jeśli a%2 = 0 (to powoduje, że połowa kluczy jest nieprawidłowa) lub a%13 = 0 to szyfrowanie nie będzie poprawne (funkcja szyfrująca nie będzie różnowartościowa)!
Rozwiązania są dwa: rozszerzyć słownik tak by liczba jego elementów, była liczbą pierwszą, albo sprawdzać, poprawność klucza!

Co do stylu kodowania, zwróć uwagę, że funkcja szyfrująca i deszyfrująca jest dokładnie taka sama, różnica jest jedynie w dostarczanym kluczu!
Przy liczeniu odwrotności klucza trzeba skorzystać z rozszerzonego algorytmu Euklidesa.

0

Zakładam, że a>0 i b>=0:

const int RozmiarSlownika = 'z'-'a'+1; // = m

// Rozszerzony algorytm Euklidesa:
int NWD(int a, int b, int *ra = 0, int *rb=0) {
    // Inicjalizacja. Utrzymujemy niezmienniki p*a0 + q*b0 = a oraz r*a0 + s*b0 = b
    int p = 1, q = 0;
    int r = 0, s = 1;
    while (b != 0) {
        int c = a%b;
        int quot = a/b;
        a = b;
        b = c;
        int new_r = p - quot * r;
        int new_s = q - quot * s;
        p = r; q = s;
        r = new_r;
        s = new_s;
    }
    if (ra)
        *ra = p;
    if (rb)
        *rb = q;
    return a;
}

void odwrotnoscKlucza(int &nowe_a, int &nowe_b, int a, int b) {
    int nwd = NWD(a, RozmiarSlownika, &nowe_a);
    assert(nwd==1); // test na poprawność klucza
    if (nowe_a<0)
        nowe_a += RozmiarSlownika;
    nowe_b = RozmiarSlownika - (b*nowe_a)%RozmiarSlownika;
}

string afiniczneSzyforwanie(const string &x, int a, int b) {
    string r(x);
    assert(NWD(a, RozmiarSlownika)==1); // test na poprawność klucza

    for (int i=0; i<r.leght(); ++i) {
        if (islower(r[i])) {
            r[i] = ( (r[i]-'a')*a+b )%RozmiarSlownika + 'a';
        } else if (isupper(r[i])) {
            r[i] = ( (r[i]-'A')*a+b )%RozmiarSlownika + 'A';
        }
    }
    return r;
}
0

Przerobiłem ten swój kod tak, że działa dla słów wpisywanych z klawiatury. Teraz tylko trzeba zrobić tak by zamiast wpisanych słów, pobierał plik binarnie i go kodował a później wynik zapisał do pliku. Wiem, że jest google i fstream ale nie potrafię go zastosować w tym kodzie dlatego proszę o jeszczę trochę trochę pomocy

#include<string.h>
#include<iostream>
using namespace std;

void code(int a, int b);
int getUncode(int a);

int main()
 {
    int a, b,c,d;
    cout<<"Wprowadź klucze kodowania K(A,B)"<<endl;
    cin>>a>>b;
    code(a,b);
    c = getUncode(a);
    d = ((256-b)*c)%256;        
    code(c,d);
    cin>>a;
    return 0;
    
}


void code(int a,int b)
{
    int  len=0,i=0,j=0,temp;
    char s[1000];
    char s1[1000];
    
    cout<<"Wprowadź tekst do zakodowania"<<endl;
     cout<<"(Uwaga! Wymagane małe litery i maksymalnie 1000 znaków.)"<<endl;
    cin>>s;
    len = strlen(s);
    for(i = 0,j = 0;i<len;i++)
    {   
        temp = (a*(s[i])+b)%256;
         if(temp<0) temp += 256; 
        s1[i]= temp;
    }
    s1[i]='\0';
    cout<<"Zakodowany ciąg znaków:"<<endl;
    cout<<s1<<endl;
}

int getUncode(int a)
{
   int c;
   c=1;
   if (a%2==0)
   {
        cout<<"Niewłasciwy klucz"<<endl;
        return 0;
    }
   while ((c*a)%256!=1)c++;
    return c;
}
0

Dodaj sprawdzenie długości tekstu wprowadzanego - unikniesz buffer overflow.

Czyli:

cin.width (1000);

http://www.cplusplus.com/reference/iostream/istream/operator%3E%3E/

0

Jeśli czytasz dane binarne ZAPOMNIJ o operatorze >>! Dałem ci linka do funkcji którą się masz posłużyć.
Zapomni też o konsoli! Bo po zakodowaniu binarnym będziesz miał różne dziwne znaki, a niektóre mają specjalne znaczenie dla konsoli!

to powinno być coś takiego:

const int BuforSize = 0x100;

void zakodujPlik(istream &zrodlo, ostream &cel, int a, int b) {
    char bufor[BuforSize];
    do {
        zrodlo.read(bufor, BuforSize);
        int n = zrodlo.gcount();
        if (n>0) {
            zakoduj(bufor, n, a, b);
            cel.write(bufor, n);
        }
    } while(zrodlo.good());
}
0

Skorzystałem z wczytywania pliku jakie zastosowałem w poprzednim programie - szyfrowanie przy pomocy algorytmu xor.
Teraz podaję plik do zakodowania (w tym samym miejscu co kompilowałem program) i plik do jakiego mają trafić dane, następnie wprowadzam klucze (nieparzyste), program wylicza klucze dekodujące i je wyświetla. Nastepnie koduje plik i jest wszystko ok.
Problem pojawia się gdy chcę zdekodować plik podając wcześniej wygenerowane klucze dekodujące.
Co zrobić by to w SPACJA końcu zadziałało? (jak to zrobić najprościej, jeżeli mozna to nie zmieniając za dużo w kodzie)
Dzięki za pomoc i cierpliwość :-)

#include <cstdlib>
#include <iostream> 
using namespace std;


int main(int argc, char *argv[])
{
    FILE *we, *wy;
    int znak;                  
    int a,b,c,d;        
    char zero='0';               
    char jeden='1';
 
    char plik_wejsciowy[255];       
    char plik_wyjsciowy[255];  
 
    cout<<"Podaj nazwe pliku wejsciowego: " ;
    cin>>plik_wejsciowy;                      
    cout<<"Podaj nazwe pliku wynikowego: ";
    cin>>plik_wyjsciowy; 
    cout<<"Wprowadz klucze kodowania K(A,B)"<<endl;
    cin>>a>>b;
    c = a;
    d = ((256-b)*c)%256;       
    cout<<"Klucze dekodujace: "<<c<<" ,"<<d<<endl;
    
 
if((we=fopen(plik_wejsciowy,"rb"))!=NULL)      
 {
    if((wy=fopen(plik_wyjsciowy,"wb"))!=NULL)  
    {
        while((znak=getc(we))!=EOF)
        {
                                   
           znak = (a*(znak)+b)%256;                     
                                    
           cout<<"   "<<znak<<endl;  
           
            putc(znak,wy);
         }
        fclose(wy);     
    }
    fclose(we);     
}
    cout<<"Operacja zostala zakonczona";
    system("PAUSE");
    return EXIT_SUCCESS;
}
0

Przecież dałem ci kod do generowania kluczy odwrotnych! Wystarczy zmienić wartość stałej m.
W mojej wersji algorytm kodujący i dekodujący są identyczne, bo w mądry sposób odwracam klucz.

1 użytkowników online, w tym zalogowanych: 0, gości: 1